线程安全事件 - 这是一种“干净”的方式吗? - 2

时间:2015-12-04 09:49:56

标签: c# multithreading

假设在这个帖子中有建设性的批评Thread-safe events - is this a "clean" way?我坐下来试图在多线程的整个主题中读到我。

以下是一些具有相同基本问题的代码:这是使用事件创建非冻结UI的既定方法吗?

public partial class Form1 : Form
{
    public delegate void MyThreadUpdateHandler(string s);

    public event MyThreadUpdateHandler MyThreadUpdate;
    System.Threading.Thread MyThread;


    public Form1()
    {
        InitializeComponent();
    }

    void DoTheCount()
    {
        int a = 0;

        while (a < int.MaxValue)
        {
            if (a % 1000000 == 0)
            {
                this.MyThreadUpdate(a.ToString());
            }

            a++;
        }
    }

    private void Form1_MyThreadUpdate(string s)
    {
        this.lblEvent.Invoke((MethodInvoker) delegate ()
        {
            lblEvent.Text = s;
        });
    }

    private void btnStartThread_Click(object sender, EventArgs e)
    {
        MyThreadUpdate += Form1_MyThreadUpdate;

        if (MyThread == null)
            MyThread = new System.Threading.Thread(new System.Threading.ThreadStart(DoTheCount));

        lblStatus.Text = "Starting thread";


        if (MyThread.ThreadState == System.Threading.ThreadState.Unstarted)
            MyThread.Start();

    }

    private void btnAbortThread_Click(object sender, EventArgs e)
    {
        MyThread.Abort();
    }
}

然而,还有一些我还没有得到的东西。为什么有些例子使用像这样的Program()? http://www.codeproject.com/Articles/667298/Using-ThreadStaticAttribute

谢谢:)

2 个答案:

答案 0 :(得分:3)

  

然而,还有一些我还没有得到的东西。为什么有一些例子   使用像这样的程序()?   http://www.codeproject.com/Articles/667298/Using-ThreadStaticAttribute

代码是

    static void Main(string[] args)
    {
        Program prog = new Program();

        //define the threads
        Thread thread1 = new Thread(new ThreadStart(prog.ThreadFunc1));
        Thread thread2 = new Thread(new ThreadStart(prog.ThreadFunc2));

这允许开发人员调用实例函数public void ThreadFunc1()&amp; public void ThreadFunc2()  来自静态功能 - static void Main(string[] args)

更新1

创建非冻结UI的既定方法是在单独的线程上进行所有耗时的活动。将调用UI线程编组以更新到它。 您实施的内容遵循相同的想法。

我想提一点,虽然它与冻结UI没有任何关系。

而不是System.Threading.Thread,请使用ThreadPool

TaskBackgroundWorkerSystem.Threading.TimerAsynchronous Programming Model都使用来自ThreadPool的帖子。或者您也可以使用ThreadPool.QueueUserWorkItem

有一个非常特殊的情况,一个人应该使用System.Threading.Thread而不是来自ThreadPool的帖子

答案 1 :(得分:2)

首先,请允许我说,我为您感到遗憾,尝试使用旧版库。

好。您有资格获得我在.net

中使用线程的几个原因之一
  

长时间运行旧版库

现在,阅读您之前的代码,我觉得您想将Rx.Net用于项目。

我首先要为您的库创建一个IObservable

public static class LibraryHelper
{
    public static IObservable<EventPattern<StatusChangedEventArg>> StatusObservable(this ComLibrary com)
    {
        return Observable.FromEventPattern<EventHandler<StatusChangedEventArg>, StatusChangedEventArg>(x => com.FooEvent +=x, x => com.FooEvent -= x);
    }
}

这将允许您将Rx.Net与您的库一起使用,如此......

private async void btnStartThread_Click(object sender, EventArgs e)
{
    ComLibary com = new ComLibray();

    lblStatus.Text = "Starting thread";

    // using is there to unsubscribe after the call, to prevent a memory leak.
    var subscription = com.StatusObservable()
       //Magic sauce 
       //http://stackoverflow.com/questions/7417978/how-to-get-a-winform-synchronization-context-or-schedule-on-a-winform-thread
      .ObserveOn(SynchronizationContext.Current)
      .Subscribe(@event => {
         //Do something on the UI thread
      });
   using(subscription)
   {
           //Task.Run uses a background thread to get the data from your COM

          var result = await Task.Run(()=> com.Read());
           //back in UI thread. Do stuff.
    }
}