C#多线程 - 使用后台事件更新GUI

Sim*_*One 5 c# multithreading

我是C#和多线程的新手,所以我很抱歉,如果这是一个重复的问题,但作为一个新手,看来我的问题与我读过的其他人略有不同.

我的GUI在一个(主)线程中运行.它调用一个后台任务(在一个dll中 - 我也在编写),它在一个单独的线程中运行.dll不了解GUI(即它不能引用GUI类).

现在,假设我想根据dll线程的状态更新GUI上的进度条 - >我正在做的是在dll中创建一个每X%将触发的事件,GUI将订阅此事件.触发事件时,GUI将更新进度条.

我的问题:

  1. 创建事件的方法是最好的方法(记住dll不能引用GUI)?
  2. 如何确保我的上述方法是"事件安全"?我应该在事件中传递进度百分比以确保线程安全吗?还是有更多信息?
  3. 更新GUI时是否需要使用Invoke?我看到一篇帖子提示我做了但我不明白为什么因为更新栏是在GUI线程中完成的??!

希望你能为我澄清一下!

谢谢

Sco*_*ain 3

1.-我一直使用这个方法,是的,它会起作用

2.-只需将 int 传递给事件处理程序,该变量就可以安全读取。但是,当您从代码中触发事件时,请这样做

private void UpdatePercentage(int a)
{
    var myEvent = PercentageUpdatedEvent
    if(myEvent != null)
         myEvent(this, new ProgressBarEventArgs(a));
}
Run Code Online (Sandbox Code Playgroud)

这样做的原因是,如果在空检查和调用之间取消订阅事件,您将不会遇到异常。

3.-正如其他人所提到的,您将需要调用 Invoke,因为该事件将在 dll 的线程上运行。然而,对于控件来说,在没有 EndEnvoike 的情况下调用 BeginInvoke 是合法的,因此该调用在 dll 线程上将是非阻塞的。

这是我经常使用的模式

private myClass_OnPercentageUpdatedEvent(object a, ProgressBarEventArgs e)
{
    if(progressBar.InvokeRequired)
        progressBar.BeginInvoke((Action<object,ProgressBarEventArgs>)myCless_OnPercentageUpdatedEvent, a, e);
    else
    {
        progressBar.Value = e.Value;
    }
}
Run Code Online (Sandbox Code Playgroud)