我正在使用Func<>或Action<> .BeginInvoke使用ThreadPool异步运行方法。
是否有可能让AsyncCallback在产生新线程的原始线程上调用一个函数(或技术上的事件)?
我知道在WinForms应用程序中,您可以使用Control / ISynchronizeInvoke / Dispatcher在异步操作完成时警告UI线程 - 但这不是WinForms应用程序,它似乎不起作用。
class SyncTest : System.ComponentModel.ISynchronizeInvoke
{
public void TestMethod() {
Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId + " Test Method Fired.");
}
public IAsyncResult BeginInvoke(Delegate method, object[] args) {
throw new NotImplementedException();
}
public object EndInvoke(IAsyncResult result) {
throw new NotImplementedException();
}
public object Invoke(Delegate method, object[] args) {
return method.DynamicInvoke(args);
}
public bool InvokeRequired {
get { throw new NotImplementedException(); }
}
public void Test()
{
var sleep = new Action(() => System.Threading.Thread.Sleep(5000));
System.ComponentModel.ISynchronizeInvoke originalThreadCallback = (System.ComponentModel.ISynchronizeInvoke)this;
for (int i = 0; i < 5; i++)
{
sleep.BeginInvoke(new AsyncCallback(res =>
{
(res.AsyncState as Action).EndInvoke(res);
Console.WriteLine("Thread inside callback: " + System.Threading.Thread.CurrentThread.ManagedThreadId);
originalThreadCallback.Invoke(new Action(() => this.TestMethod()), null);
}), sleep);
}
}
}
Test()方法的输出如下:
主线程= 9
TEST DONE
回调中的线程:11
回调中的线程:10
10种测试方法被解雇。
11测试方法被解雇。
回调中的线程:12
12测试方法被解雇。
回调中的线程:13
13测试方法被解雇。
回调中的线程:14
14测试方法被解雇。
正如您所看到的,ID = 9的原始线程上没有调用任何内容。
显然我的ISynchronizeInvoke实现实际上没有做任何事情来调用原始线程上的Test方法,这就是问题所在 - 但我似乎也无法从我的任何委托或事件中获取ISynchronizeInvoke实例(它总是为空)。 .NET 4中的哪些对象正确实现了接口?
感谢。
答案 0 :(得分:2)
好吧,你必须有一些循环,就像Windows Forms(等)那样,等待工作处理。
你可以自己编写,但这意味着你的原始线程必须保持相对自由,就像你不想阻止Windows窗体应用程序中的UI线程一样。基本上,您将重写WinForms使用的一些基础结构。虽然.NET 4生产者/消费者队列类(例如BlockingCollection<T>
)至少帮助,但我没有意识到这只是开箱即用的。
BlockingCollection<T>
的文档给出了一个如何实现生产者/消费者队列的快速示例 - 基本上你的线程池线程会在队列上调用Add
,而你的消费者线程会调用Take
在它上面(或TryTake
)。
还有一个Channel-9 video与专家Stephen Toub(MS中的并行团队)关于使用BlockingCollection
。