C#线程中止

时间:2018-12-02 16:01:01

标签: c# multithreading winforms

在我的主要表单正在加载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();
    });
}

1 个答案:

答案 0 :(得分:0)

这是我所能得到的紧凑:

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()));

对于使用异步的替代方法,请约束以下内容:

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设置为子窗体来解决此问题。 / p>

另一个区别是,在这种情况下,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();
}