在我的主要表单正在加载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();
});
}
答案 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
是在另一个线程中运行的部分。现在,它需要BeginInvoke
与MainForm
进行交互。
从那里我们可以轻松地转到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();
}