在关闭表单之前停止线程

Posted

技术标签:

【中文标题】在关闭表单之前停止线程【英文标题】:stop a thread before closing form 【发布时间】:2016-10-24 19:43:33 【问题描述】:

使用 .NET4、c#、 我在winform上有一个网格。当我点击一个进程按钮时,我需要对每一行执行几个步骤的及时操作,然后用结果更新该行。这样,用户可以在处理下一行时看到进度。如果用户点击取消或关闭表单,我需要完成当前行的过程,然后中断或关闭表单。根据我的研究,这是我想出的。我还有 2 个问题。

这是我的代码:

delegate void OperateGridMethodDelegate();
delegate void UpdateProgressDelegate(int rowIndex, string msg);
bool isCancelled = false;


private void ButtonOne_Click(object sender, EventArgs e)

    isCancelled=false;
    OperateGridMethodDelegate delegate = new OperateGridMethodDelegate(LongProcess);`
    delegate.BeginInvoke(null,null);



private void ButtonTow_Click(object sender, EventArgs e)


    MyButtonOne.Enabled=false;
    isCancelled=true;



private void LongProcess()


    foreach (DataRow row in dataTableOne.Rows)
    
        //Do Lengthy Process

        DisplayResult( rowIndex, "this is result of operation" );
        if(isCancelled)
        
            MyButtonOne.Enabled=true;
            break;

        

    



private void DisplayResult(int rowIndex,string message)


    if(myGrid.InvokeRequired == false)
    

        myGrid.Rows[rowIndex].value = message;

    

    else
    

        UpdateProgressDelegate delegate = new  UpdateProgressDelegate(DisplayResult);
        myGrid.BeginInvoke(delegate, new object[]  rowIndex, message );

    


我剩下的两个问题是:

    当表单关闭时,我想等待 LongProcess(由我的 OperateGridMethodDelegate 调用)完成它的行,然后取消(与 ButtonTwo 一样),但我可以'让这个工作。

    我在调试时注意到一个奇怪的行为,我不确定这是一个错误还是正确的,当一行完成处理时,结果没有设置。相反,处理下一行,然后显示上一行结果。当第三行结束时显示第二行结果等。然后最后两行结果基本同时显示。

我的方法正确吗?

【问题讨论】:

不要使用委托的 BeginInvoke() 方法来实现线程,bool 不是同步原语。有更好的方法可以做到这一点,this Q+A 中介绍了如何正确处理 BackgroundWorker。 【参考方案1】:

如果你在一个线程中启动了一些任务,等待它完成后再继续你可以这样做:

yourThread.Join();

这将阻塞直到线程退出。您可能想在 Form_Closing 事件中使用类似的东西

或者,如果您希望线程在应用程序终止时自动终止,您需要设置线程的背景属性:

yourThread.IsBackground = true;

这意味着它是您的主 (UI) 线程的后台线程,因此它将以主线程结束。

编辑:

使用你自己的线程:

private Thread yourThread = new Thread(() = > LongProcess());
yourThread.IsBackground = true;
yourThread.Start();  // This will begin your 'LongProcess' function.

现在如果你想在某个地方阻塞并等待它完成,你可以做我首先提到的:yourThread.Join();

另请注意,如果您设置了IsBackground = false 并且有人关闭了应用程序,则该线程不会立即退出,它会一直持续到完成为止,尽管 UI 窗口已关闭。

【讨论】:

你的线程是什么?我在哪里得到这个?我没有完全遵循 我在答案中添加了更多内容。如果你想控制线程,你应该使用你自己的Thread对象 你是不是想说,而不是我的代码 - private void ButtonOne_Click(object sender, EventArgs e) isCancelled=false; OperateGridMethodDelegate 委托 = 新的 OperateGridMethodDelegate(LongProcess);`delegate.BeginInvoke(null,null); ,我应该这样做吗?私人无效ButtonOne_Click(对象发送者,EventArgs e)isCancelled=false;私有线程 yourThread = new Thread(() = > LongProcess());你的线程.IsBackground = true;你的线程.Start(); 我不会按照您通常的方式进行操作,但考虑到您想要对长期运行的任务进行控制,使用您自己的Thread 绝对是可取的。您可能会在声明 delegate void 的位置声明线程,并在 ButtonOne_Click 事件中声明 .Start() 线程 你介意告诉我你会如何建议这样做吗?我不打算只这样做?

以上是关于在关闭表单之前停止线程的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C# 中按下停止按钮来停止耗时过长的 UI 线程 [关闭]

如何在窗体的关闭事件中停止 BackgroundWorker?

关闭 QT GUI 后如何停止线程

如果程序关闭,Java如何停止线程

线程池的停止

再次运行应用程序时如何停止关闭的应用程序留下的线程? C#