“做一些工作和戒烟”的最佳模式

时间:2010-09-22 14:18:48

标签: c# multithreading

我目前正在编写一个GUI程序,可以完成一些工作并在之后退出。工作完成后,GUI线程将使用信息为用户更新。

这是我目前正在使用的模式,我认为这不是最优雅的模式:

static void MainForm_Loaded(BeoExport exporter)
{
    // Thread 1 runs the Export
    workerThread = new Thread(() =>
    {
        exporter.StartExport();
        // don't exit immediately, so the user sees someting if the work is done fast
        Thread.Sleep(1000);     
    });

    // Thread 2 waits for Thread 1 and exits the program afterwards
    waiterThread = new Thread(() =>
    {
        workerThread.Join();
        Application.Exit();
    });

    workerThread.Start();
    waiterThread.Start();
}

那么你会用什么模式/机制来做同样的事情?

澄清一下:我对更新GUI线程的方式不感兴趣。那已经完成了。这可能听起来很深奥,但我很想找到退出应用程序的正确方法。

如果可以的话,我会给予Dave学分,因为他指出了BackgroundWorker的用处。

8 个答案:

答案 0 :(得分:2)

您是否考虑过BackgroundWorker线程?您可以使用其ReportProgress方法和ProgressChanged事件更新GUI(可能包含进度条),假设您可以重构BeoExport.StartExport方法以报告进度。这为用户提供了实际工作正在发生的可见反馈。

答案 1 :(得分:2)

我不明白你为什么要使用两个线程。你可以使用threadpool:

ThreadPool.QueueUserWorkItem((state)=>{
    exporter.StartExport();
    Thread.Sleep(1000);
    Application.Exit();
});

答案 2 :(得分:2)

我建议您使用BackgroundWorker课程。它被认为是做你正在做的那种工作。你可以这样做:

public class Form1 : Form
{
    private BackgroundWorker worker;
    private ProgressBar bar;
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        bar= new ProgressBar();
        bar.Dock = DockStyle.Top;
        Controls.Add(bar);

        worker = new BackgroundWorker();
        worker.WorkerReportsProgress=true;
        worker.RunWorkerCompleted += delegate
                                         {
                                             Close();
                                         };
        worker.ProgressChanged += delegate(object sender, ProgressChangedEventArgs ev)
                                      {
                                          bar.Value = ev.ProgressPercentage;
                                      };
        worker.DoWork += worker_DoWork;
        worker.RunWorkerAsync();
    }

    void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        //do your work here. For the example, just sleep a bit 
        //and report progress
        for (var i = 0; i < 100;i++ )
        {
            Thread.Sleep(50);
            worker.ReportProgress(i);
        }
    }

}

答案 3 :(得分:1)

您可以使用AutoResetEvent。主线程等待重置autoreset事件。

var wh = new AutoResetEvent(false);

var workerThread = new Thread(() =>
{
    exporter.StartExport();
    // don't exit immediately, so the user sees something if the work is done fast
    Thread.Sleep(5000);
    wh.Set();
});

workerThread.Start();
wh.WaitOne();

Application.Current.Shutdown();

答案 4 :(得分:1)

你有没有看过。{4}中的Task Parallel Library你可以设置一个任务,库会为你做最好的解决方案,无论是线程化,还是单独的CPU内核都是一个负载关于它的重要信息。

此致

伊恩

答案 5 :(得分:1)

为Lain的回答添加一点,这是使用System.Threading.Tasks命名空间中的任务的控制台示例。

 class Program
    {
        static void Main(string[] args)
        {

            Task<int> task  = Task<int>.Factory.StartNew(() =>
                {
                    Exporter exporter = new Exporter();
                    int i = exporter.StartExport();
                    return i;
                 });

            int iResult = task.Result;
            Console.WriteLine(iResult);
            Console.ReadLine();


        }

        class Exporter {
            public int StartExport()
            {
                //simulate some work
                System.Threading.Thread.Sleep(500);
                return 5;
            }
        }
    }

答案 6 :(得分:1)

使用BackgroundWorker可能会帮助您实施后台处理。如果您想坚持使用当前模式,请考虑以下内容。

static void MainForm_Loaded(BeoExport exporter) 
{ 
    workerThread = new Thread(() => 
    { 
        exporter.StartExport(); 
        Thread.Sleep(1000);      
        MainForm.BeginInvoke(
          (Action)(() =>
          {
            MainForm.Close();
          });
    });
    workerThread.IsBackground = true;
    workerThread.Start();
} 

答案 7 :(得分:0)

让工作线程向主线程发送一些描述的通知消息。然后,GUI可以根据需要退出或显示“完成”消息。