正常关闭线程

Cod*_*ter 6 c# multithreading

在我正在开发的应用程序中,我有一个主要表单,它只是位于那里并显示日志数据,以及一个自动完成循环工作的工作线程.

MyWorker worker = new MyWorker();
MainForm mainForm = new MainForm();

// Subscribe form to log event so log data gets displayed
worker.Log += mainForm.Log;

// Start the worker thread's MainLoop
new Thread(new ThreadStart(worker.MainLoop)).Start();

// Show the form (blocking)
Application.Run(mainForm);

// If we end up here, the form has been closed and the worker has to stop running            
worker.Running = false;
Run Code Online (Sandbox Code Playgroud)

如您所见,无论何时关闭表单,都应该停止工作线程.工人看起来像这样:

public class MyWorker
{
    public String Running { get; set; }

    public MyWorker()
    {
        Running = true;
    }

    public void MainLoop()
    {

        while (Running)
        {

            DoExtensiveWork1();
            if (!Running) return;

            DoExtensiveWork2();
            if (!Running) return;

            DoExtensiveWork3();
            if (!Running) return;

            DoExtensiveWork4();
            if (!Running) return;

            DoExtensiveWork5();         
            if (!Running) return;

            // We have to wait fifteen minutes (900 seconds) 
            // before another "run" can be processed
            for (int i = 0; i < 900; i++)
            {
                Thread.Sleep(1000);
                if (!Running) return;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如您所见,我希望线程能够在连续的工作操作之间切换时停止,但不能在操作中停止.当一个operation(DoExtensiveWorkN)完成后,它的状态和结果会持久存在于磁盘或数据库中,因此在操作正在进行时(例如,通过Thread.Abort)退出不是一个选项.

但是,我发现这个代码我刚刚写了一些令人厌恶的代码,特别是"等待循环",它休眠了900秒,以防止线程在检测Running到之前空转15分钟false.

我宁愿能够在完成一项工作后立即抛出某种事件来阻止主循环.

任何人都可以指出我正确的方向如何做到这一点,或者如果需要完全重写因为我完全误解了线程,请告诉我哪些原则被解释了?

Iri*_*ium 14

您可以大大整理单个任务的运行和15分钟的等待循环.

我建议也许使用这样的东西:

public class MyWorker
{
    private readonly ManualResetEvent _stopEvent = new ManualResetEvent(false);
    private readonly Action[] _workUnits;

    private bool Running
    {
        get { return !_stopEvent.WaitOne(0); }
    }

    public MyWorker()
    {
        _workUnits = new Action[]
        {
            DoExtensiveWork1,
            DoExtensiveWork2,
            DoExtensiveWork3,
            DoExtensiveWork4,
            DoExtensiveWork5
        };
    }

    public void Stop()
    {
        _stopEvent.Set();
    }

    public void MainLoop()
    {

        while (Running)
        {
            foreach (var workUnit in _workUnits)
            {
                workUnit();
                if (!Running) return;
            }           

            // We have to wait fifteen minutes (900 seconds) 
            // before another "run" can be processed
            if (_stopEvent.WaitOne(900000)) return;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在下一个适当的点停止该过程:

Worker.Stop();
Run Code Online (Sandbox Code Playgroud)