我有一个简单的情况:
public partial class Form1 : Form {
Task t;
public Form1() {
InitializeComponent();
t = Prepare();
}
public Task waitT() {
return Task.Factory.StartNew(() => {
for (int i = 0; i < 5; i++) {
Thread.Sleep(1000);
Console.WriteLine("T works \n");
}
});
}
public Task waitT2() {
return Task.Factory.StartNew(() => {
for (int i = 0; i < 3; i++) {
Thread.Sleep(1000);
Console.WriteLine("T2 works \n");
}
});
}
public Task waitT3() {
return Task.Factory.StartNew(() => {
for (int i = 0; i < 2; i++) {
Thread.Sleep(1000);
Console.WriteLine("T3 works \n");
}
});
}
public async Task Prepare() {
//await Task.Factory.StartNew(async () => {
await waitT();
Console.WriteLine("T DOne.");
await waitT2();
Console.WriteLine("T2 DOne.");
await waitT3();
Console.WriteLine("T3 DOne.");
// });
}
protected override void OnPaint(PaintEventArgs e) {
base.OnPaint(e);
t.Wait();
Console.WriteLine("Finish");
}
}
简而言之,我想在构造函数中启动一个任务,然后等待Paint事件中的一些数据。问题是在wait()方法中执行被阻塞,并且永远不会调用代码Console.WriteLine(“ TDone。”)。我已经读过,异步方法的执行是第一次同步,我认为问题是这样的。 为了尝试解决该问题,我更改了功能代码,准备方法如下:
public async Task Prepare() {
return await Task.Factory.StartNew(async () => {
await waitT();
Console.WriteLine("T DOne.");
await waitT2();
Console.WriteLine("T2 DOne.");
await waitT3();
Console.WriteLine("T3 DOne.");
});
}
通过这种方式,情况发生了变化,并且不使用paint中的wait方法,执行立即传递给Console.WriteLine(“ Finish”)和Prepare进程正在运行。
可能是我犯了一个秘密错误,有人可以向我解释这样做的正确方法吗?
谢谢
答案 0 :(得分:0)
您正陷入僵局,因为您从异步切换到同步,并且两个事物/进程具有不同的同步上下文。 您不能使构造函数异步,但可以将其包装到等待的任务中作为解决方法:
public Form1() {
InitializeComponent();
Task.WaitAll(Task.Run( async ()=> await Prepare()));
}
您实际上并不需要Task t
变量。由于Prepare
不会产生任何返回值,因此您可以等待它。我想您是通过这个例子来说明您遇到的一些问题。通常,如果您从async
和await
开始,则需要将其提升到GUI的最高级别。同步处理的任何中断都会导致死锁
编辑: 发表评论后:
我想创建一个长期运行的任务(构造函数示例错误),运行它,然后在需要结果时检查任务是否完成(例如在事件中)。
我建议在构造函数中启动任务:
t = Task.Run(async ()=> await Prepare());
并在必须创建OnPaint
的{{1}}事件中等待它,以便它不会阻塞UI:
async
答案 1 :(得分:0)
[编辑] 我更改了代码,从构造函数中删除了任务分配,并在加载事件中将其移动:
public partial class Form1 : Form {
Task t;
public Form1() {
InitializeComponent();
}
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
t = Prepare();
}
public Task waitT() {
return Task.Run(() => {
for (int i = 0; i < 5; i++) {
Thread.Sleep(1000);
Console.WriteLine("T works \n");
}
});
}
public Task waitT2() {
return Task.Run(() => {
for (int i = 0; i < 3; i++) {
Thread.Sleep(1000);
Console.WriteLine("T2 works \n");
}
});
}
public Task waitT3() {
return Task.Run(() => {
for (int i = 0; i < 2; i++) {
Thread.Sleep(1000);
Console.WriteLine("T3 works \n");
}
});
}
public async Task Prepare() {
await Task.Run(async () => {
await waitT();
Console.WriteLine("T DOne.");
await waitT2();
Console.WriteLine("T2 DOne.");
await waitT3();
Console.WriteLine("T3 DOne.");
});
}
protected override void OnPaint(PaintEventArgs e) {
base.OnPaint(e);
t.Wait();
Console.WriteLine("Finish");
}
}
现在结果有所不同,我等待正确的3个wait方法结束,但是尽管3个方法结束,执行仍然在t.wait()中阻塞。 Console.WriteLine(“ Finish”);不被称为:(
[编辑2] 可能我已经解决了我的问题,并且我可以使用其他方法在构造函数中创建任务,此代码可以正常工作(这仅是带有事件的示例):
public partial class Form1 : Form {
Task t;
public Form1() {
InitializeComponent();
t = Prepare();
}
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
}
public Task waitT() {
return Task.Run(() => {
for (int i = 0; i < 5; i++) {
Thread.Sleep(1000);
Console.WriteLine("T works \n");
}
});
}
public Task waitT2() {
return Task.Run(() => {
for (int i = 0; i < 3; i++) {
Thread.Sleep(1000);
Console.WriteLine("T2 works \n");
}
});
}
public Task waitT3() {
return Task.Run(() => {
for (int i = 0; i < 2; i++) {
Thread.Sleep(1000);
Console.WriteLine("T3 works \n");
}
});
}
public Task Prepare() {
return Task.Run(async () => {
await waitT();
Console.WriteLine("T DOne.");
await waitT2();
Console.WriteLine("T2 DOne.");
await waitT3();
Console.WriteLine("T3 DOne.");
});
}
protected override void OnPaint(PaintEventArgs e) {
base.OnPaint(e);
t.Wait();
Console.WriteLine("Finish");
}
}