C#线程中止

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#线程中止相关的知识,希望对你有一定的参考价值。

我使用Thread查看等待表单,而我的主要表单正在加载Load事件。但有时我会得到一个ThreadAbortException,上面写着“线程被中止了”。

请帮我解决这个问题。

主窗体加载事件代码:

WaitingForm wf;

MainForm_Load(object sender, EventArgs e)
{
        Thread t = new Thread(new ThreadStart(delegate
        {
            wf = new WaitingForm();
            wf.ShowDialog();
        }));
        t.Start();

        /***** Do Something *****/

        if (wf != null)
            wf.closeLoad();
        t.Abort();
}

WaitingForm CloseLoad功能:

public void closeLoad()
{
    Invoke((MethodInvoker)delegate
    {
        this.Close();
    });
}
答案

这是我能得到的紧凑:

var waitingForm = new WaitingForm();
(new Thread (() => Application.Run(waitingForm))).Start();
HeavyWork();
waitingForm.BeginInvoke(new Action(() => waitingForm.Close()));

waitingForm将完全响应,使用自己的消息循环在匿名线程上运行。但是,由于它在另一个线程上运行,我们需要BeginInvoke来关闭它。

我们可以用Task交换这个火并忘记线程:

var waitingForm = new WaitingForm();
Task.Run(() => Application.Run(waitingForm));
HeavyWork();
waitingForm.BeginInvoke((Action)(() => waitingForm.Close()));

对于使用async的替代方法,请考虑以下事项:

var source = new TaskCompletionSource<int>();

Enabled = false;
ShowWaitForm();
await HeavyWorkAsync();
Enabled = true;
source.SetResult(0);

async void ShowWaitForm()
{
    var waitingForm = new WaitingForm();
    waitingForm.Show(this);
    await source.Task;
    waitingForm.Close();
}

这次我们使用TaskCompletionSource通知工作已经完成并且WaitingForm可以关闭,以便我们可以等待它。

用户将会有一个不同之处:MainForm将是可见的,甚至可以响应......我们通过禁用它并使WaitingForm成为子形式来解决这个问题。

另一个区别是,在这种情况下,WaitingForm没有自己的消息循环。但是,只要您使用异步方法来完成工作,它仍然会响应。

请记住,它是处理两种形式的单个线程。这可能是也可能不方便。

你总是可以回退使用Task.Run

var source = new TaskCompletionSource<int>();

Enabled = false;
ShowWaitForm();
await Task.Run(() => HeavyWork());
Enabled = true;
source.SetResult(0);

async void ShowWaitForm()
{
    var waitingForm = new WaitingForm();
    waitingForm.Show(this);
    await source.Task;
    waitingForm.Close();
}

请注意,在Task.Run上使用HeavyWork时,HeavyWork是在另一个线程中运行的部分。现在,需要BeginInvokeMainForm互动。

从那里我们可以很容易地去BackgroundWorker

var source = new TaskCompletionSource<int>();

Enabled = false;
ShowWaitForm();
var bg = new BackgroundWorker();
bg.DoWork += (_, __) => HeavyWork();
bg.RunWorkerCompleted += (_, __) =>
{
    Enabled = true;
    source.SetResult(0);
};
bg.RunWorkerAsync();


async void ShowWaitForm()
{
    var waitingForm = new WaitingForm();
    waitingForm.Show(this);
    await source.Task;
    waitingForm.Close();
}

以上是关于C#线程中止的主要内容,如果未能解决你的问题,请参考以下文章

中止请求时 IIS/C# 中会发生啥

C# 中止线程:此平台不支持线程中止

在 .NET 中中止线程时,这段代码会损坏吗?

线程在完成执行代码之前在动态库中中止

我的文件由于线程而被锁定,即使中止它也没有被终止

Python ThreadPoolExecutor 异常中止解决方案