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

C# 在AsyncCallback(控制台应用程序)内的原始线程上激发事件,c#,.net,asynchronous,synchronization,threadpool,C#,.net,Asynchronous,Synchronization,Threadpool,我正在使用Func或Action.BeginInvoke使用线程池异步运行方法 是否可以让AsyncCallback调用生成新线程的原始线程上的函数(或者技术上的事件) 我知道在WinForms应用程序中,您可以使用Control/ISynchronizeInvoke/Dispatcher在异步操作完成时向UI线程发出警报——但这不是WinForms应用程序,而且似乎不起作用 class SyncTest : System.ComponentModel.ISynchronizeInvok

我正在使用Func或Action.BeginInvoke使用线程池异步运行方法

是否可以让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);
            }
        }
    }
类SyncTest:System.ComponentModel.ISynchronizeInvoke
{
公共void TestMethod(){
Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId+“激发了测试方法”);
}
公共IAsyncResult BeginInvoke(委托方法,对象[]args){
抛出新的NotImplementedException();
}
公共对象EndInvoke(IAsyncResult结果){
抛出新的NotImplementedException();
}
公共对象调用(委托方法,对象[]args){
返回方法DynamicInvoke(args);
}
需要公共布尔调用{
获取{抛出新的NotImplementedException();}
}
公开无效测试()
{
var sleep=newaction(()=>System.Threading.Thread.sleep(5000));
System.ComponentModel.ISynchronizeInvoke originalThreadCallback=(System.ComponentModel.ISynchronizeInvoke)此;
对于(int i=0;i<5;i++)
{
sleep.BeginInvoke(新异步回调(res=>
{
(res.asynchstate as Action).EndInvoke(res);
WriteLine(“回调内的线程:+System.Threading.Thread.CurrentThread.ManagedThreadId”);
originalThreadCallback.Invoke(新操作(()=>this.TestMethod()),null);
})睡眠);
}
}
}
Test()方法的输出如下所示:

主螺纹=9

测试完成

内部线程回调:11

线程内部回调:10

10试验方法

11试验方法

回调内线程:12

12试验方法

内部线程回调:13

13试验方法

内部线程回调:14

14试验方法

正如您所看到的,在ID=9的原始线程上没有调用任何内容

显然,我的ISynchronizeInvoke实现实际上并没有在原始线程上调用测试方法,这就是问题所在——但我似乎也无法从任何委托或事件中获取ISynchronizeInvoke实例(它总是空的)。NET 4中的哪些对象正确实现了接口


谢谢

好吧,您必须像Windows窗体(etc)一样进行某种循环,等待处理工作

您可以自己编写,但这意味着您的原始线程必须保持相对自由,就像您不想在Windows窗体应用程序中阻止UI线程一样。基本上,您将重写WinForms使用的一些基础结构。虽然.NET4生产者/消费者队列类(例如)至少会有所帮助,但据我所知,没有任何一种方法可以直接做到这一点

BlockingCollection
的文档提供了一个如何实现生产者/消费者队列的快速示例-基本上,线程池线程会在队列上调用
Add
,消费者线程会在队列上调用
Take
(或
TryTake


关于使用
BlockingCollection

基本上,我想要一个线程专门用于执行一些IO操作(主要是文件IO)。我的理由是,在并发环境中,无论如何我都必须锁定()这些操作,因此最好让一个线程从各种异步线程池线程接收事件通知,并相应地采取行动。我明白你的意思,线程必须是相对自由的——基本上我只希望该线程对来自其他线程的事件做出反应,这是它的唯一目的。@SeanThoman:听起来你基本上只需要一个生产者/消费者队列来处理这个问题。最初产生工作的线程是否是使用者并不重要,您只需要将工作添加到队列中。你使用的是什么版本的.NET?@JohnSkeet:没错,它是否是原始线程并不重要,只需要一个用于同步处理事件的线程(我认为基本上是一个事件循环)。其思想是,执行其他工作的线程不必等待IO被锁定()。我在用.NET4。@SeanThoman:好的,很高兴知道你在用.NET4。你应该考虑使用<代码>任务<代码>来安排工作而不是<代码>开始调用> /代码> -它以各种方式更简单:无论如何,我已经用一些链接编辑了我的答案…我怀疑
BlockingCollection
将是您前进的方向。