在AsyncCallback(控制台应用程序)内部的原始线程上激发事件
本文关键字:线程 原始 事件 内部 AsyncCallback 控制台 应用程序 | 更新日期: 2023-09-27 18:20:30
我正在使用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
测试完成
线程内部回调:11
线程内部回调:10
10试验方法。
11试验方法。
线程内部回调:12
12试验方法。
线程内部回调:13
13燃烧的试验方法。
线程内部回调:14
14试验方法。
正如您所看到的,在ID为9的原始线程上没有调用任何内容。
显然,我的ISynchronizeInvoke实现实际上并没有在原始线程上调用测试方法,这就是问题所在——但我似乎也无法从我的任何委托或事件中获得ISynchronize invoke实例(它总是空的)。.NET 4中的哪些对象正确地实现了接口?
谢谢。
好吧,你必须有某种循环,就像Windows窗体(etc)所做的那样,等待工作的处理。
你可以自己写,但这意味着你的原始线程必须保持相对自由,就像你不想阻止Windows窗体应用程序中的UI线程一样。基本上,您将重写WinForms使用的一些基础设施。据我所知,没有什么是开箱即用的,尽管.NET 4生产者/消费者队列类(例如BlockingCollection<T>
)至少会对有所帮助。
BlockingCollection<T>
的文档提供了一个如何实现生产者/消费者队列的快速示例——基本上,您的线程池线程将在队列上调用Add
,消费者线程将在其上调用Take
(或TryTake
)。
还有一个与专家Stephen Toub(来自微软并行团队)在第九频道的关于使用BlockingCollection
的视频。