在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中的哪些对象正确地实现了接口?

谢谢。

在AsyncCallback(控制台应用程序)内部的原始线程上激发事件

好吧,你必须有某种循环,就像Windows窗体(etc)所做的那样,等待工作的处理。

你可以自己写,但这意味着你的原始线程必须保持相对自由,就像你不想阻止Windows窗体应用程序中的UI线程一样。基本上,您将重写WinForms使用的一些基础设施。据我所知,没有什么是开箱即用的,尽管.NET 4生产者/消费者队列类(例如BlockingCollection<T>)至少会对有所帮助。

BlockingCollection<T>的文档提供了一个如何实现生产者/消费者队列的快速示例——基本上,您的线程池线程将在队列上调用Add,消费者线程将在其上调用Take(或TryTake)。

还有一个与专家Stephen Toub(来自微软并行团队)在第九频道的关于使用BlockingCollection的视频。