C# 通过在线程库中处理,消除调用()的需要

C# 通过在线程库中处理,消除调用()的需要,c#,wpf,winforms,multithreading,C#,Wpf,Winforms,Multithreading,在我正在编写的类库中,我有一个方法,允许类库在不同的线程上执行某些操作,这类似于: public void DoStuffAsync(AP p) { this.Running = true; this.Cancel = false; ParameterizedThreadStart threadStart = new ParameterizedThreadStart(DoStuff); Thread procThr

在我正在编写的类库中,我有一个方法,允许类库在不同的线程上执行某些操作,这类似于:

    public void DoStuffAsync(AP p)
    {
        this.Running = true;
        this.Cancel = false;

        ParameterizedThreadStart threadStart = new ParameterizedThreadStart(DoStuff);
        Thread procThread = new Thread(threadStart);
        procThread.Start(p);
    }
我还在接口上声明了许多事件,开发人员可以将它们挂接到其中,例如StatusUpdate和ProgressUpdate。我目前正在编写一个小测试应用程序(目前在WPF中,尽管我希望WinForms中也会有同样的行为),它调用DoStuffAsync(),然后更新进度条和标签

不幸的是,第一次通过时我出现了一个错误,通常的线程不是拥有控件的线程。我想做的是消除用户在UI端调用Invoke()的需要,让他们只订阅事件并让它们工作

所以问题是,在处理事件处理程序时,有没有一种方法可以在我的代码中实现这一点?目前的触发方式如下:

        public void UpdateProgress(object sender, ProgressEventArgs e)
        {
            if (handler != null)
            {
                handler(sender, e);
            }
        }

您将需要对客户端的Dispatcher对象的引用,以便可以调用Dispatcher.Invoke或Dispatcher.BeginInvoke来封送对客户端UI线程的调用。通过让客户机通过构造函数或属性为您提供所需的引用来实现这一点

另一种方法是在类构造函数中存储对SynchronizationContext.Current的引用。使用它的Send或Post方法。但是,这需要客户端正确初始化WPF(必须调用Application.Run)并从其UI线程构造类对象。

请改用

它将为您执行调用。
(在内部,它使用nobugz描述的SynchronizationContext)

很酷,现在Winforms又如何呢?还有调度程序对象吗?@cmw-yes(.InvokeRequired和Invoke对控件执行相同的操作)@nobugz-不幸的是,我不确定我能做到这一点,在我的示例应用程序中可能有许多控件,例如label、progress bar和canvas,将所有这些都传递到构造中,并且知道哪一个控件与哪个事件相关联会很麻烦。我还没有尝试过,但我猜WebClient.DownloadAsync()会遇到与我所面临的问题类似的问题,需要调用?没问题,所有控件只有一个Dispatcher对象。有趣的是,我对Dispatcher了解不够。这看起来正是我需要的资源,事实上,它进入了整个异步和基于事件的模型,这正是我试图做的。真希望我在设计中早点知道这个资源!虽然我走了这条路,但实际上我回到了我的原始代码。我发现SynchronizationContext.Post方法实际上在将消息泵送回UI时非常慢。这只是一个“我也是”,但我要补充一点:在我执行的一个操作中,如果它是在UI线程/上下文上启动的,它将在几秒钟内进行评估。在来自非UI线程的SynchronizationContext.Send(…)调用下,花费了分钟。