这个问题和许多其他问题类似,但又不一样。我需要像 BeginInvoke
这样的方法来处理 Winforms,但不仅限于 Winforms。因此,我需要一个适用于任何应用程序类型的单一方法,因此我正在调用。
void ExecuteInMainContext(Action action)
{
...
}
希望这个方法可以在控制台、WinForms、WPF等应用中调用,并且不会出现问题。我看到的所有方法都是使用 BeginInvoke
在 WinForms 上,使用 Dispatcher.Invoke
在 WPF 上等等。但是我需要从库中调用它,并且我不知道从哪里调用它。同时,对于调用代码来说,它也应该是透明的,因此不应该传递像指向调用主线程的指针之类的东西,库应该从环境本身获取这些信息,而不是从用户代码或任何全局变量中获取。
我尝试使用 Task.ConfigureAwait
,但它并没有帮助。
我找到了这篇文章:
在控制台应用程序中,除非经过大量工作,否则无法完成此操作。TPL内置的机制用于将回调调度到线程上,这可能取决于线程是否安装了 SynchronizationContext。这通常由用户界面框架(即:Windows Forms 中的 Application.Run,或者在 WPF 的启动代码中等)安装。
但我希望这是可能的。
下面是测试代码:
using System;
using System.Threading;
namespace Test
{
class Program
{
private static void Main(string[] args)
{
Console.WriteLine("Main: " + Thread.CurrentThread.ManagedThreadId);
Publisher publisher = new Publisher(Method);
Console.ReadLine();
}
private static void Method(string s)
{
Console.WriteLine(s + " " + Thread.CurrentThread.ManagedThreadId);
}
}
class Publisher
{
public event Action<string> Action;
protected virtual void OnAction(string obj)
{
Action<string> handler = Action;
if (handler != null)
{
SafeCall(() => handler(obj));
}
}
private static void SafeCall(Action action)
{
// ???
action(); // should write 1
}
public Publisher(Action<string> action)
{
Action = action;
Console.WriteLine("Publisher thread: " + Thread.CurrentThread.ManagedThreadId);
Thread thread = new Thread(() => OnAction("hello"));
thread.Start();
}
}
}
所以它应该在任何地方写入相同的数字。