我有一个表单,如下所示,接受Task<T>
,等待完成,然后在await
之后通过关闭表单返回:
public partial class SomeForm<T> : Form
{
public T ReturnValue { get; private set; }
private Task<T> Task { get; set; }
public SomeForm(string waitingText, Task<T> task)
{
InitializeComponent();
...
PerformTask();
}
private async void PerformTask()
{
ReturnValue = await Task;
this.Close();
}
}
然而,虽然这种方法运行得很愉快,但它会进入ReturnValue = await Task;
然后再进一步。该方法将正常运行而不会被发送到该方法,并且不会延迟。我觉得这与我使用async
和await
的方式有关,但我是TPL等的新手。
请帮我识别上述脚本的错误,并确定它永远不会返回的原因。
编辑:TaskA是一个错字。这是Task的方法; ImportedFunctions。 BS_Robots_LoadDrive(..)
是一个C ++函数的DllImport,它可以很好地同步工作,即使在另一个线程上(比如在最后的代码片段中),但不是async
参数。
public uint LoadDisc()
{
uint response = ImportedFunctions.BS_Robots_LoadDrive(DriveLetters[0],
(int)BSRobotConstants.BIN_ID_DEFAULT,
(int)BSRobotConstants.POSITION_TYPE_INPUTBIN,
0);
switch (response)
{
case BSRobotConstants.OK:
case BSRobotConstants.OK_WITH_MESSAGE:
case BSRobotConstants.FROMTRAY_NO_DISC:
case BSRobotConstants.INVALID_DRIVE:
case BSRobotConstants.INVALID_POSITION:
case BSRobotConstants.TOTRAY_NO_DISC:
case BSRobotConstants.TOTRAY_NOT_OPEN:
case BSRobotConstants.FATAL_ERROR:
break;
case BSRobotConstants.BUSY:
break;
case BSRobotConstants.TOTRAY_HAS_DISC:
RejectDisc();
response = LoadDisc();
break;
}
return response;
}
这有效:
private async void PerformTask()
{
Task.Start();
Task.Wait();
ReturnValue = Task.Result;
DialogResult = DialogResult.OK;
}
但第一段代码片段没有。
答案 0 :(得分:2)
任务不会继续ReturnValue = await TaskA;
,因为它没有返回。验证Task
是否正在运行且不会卡住。
要使用对象构造的属性实用程序async
- await
,请使用异步工厂方法。
请参阅:How to initialize an object using async-await pattern
public class Form1<T> : Form
{
public Form1(string waitingText, Task<T> task)
{
Task = Execute(task);
Controls.Add(new Label { Text = waitingText });
}
public T ReturnValue { get { return Task.Result; } }
public Task<T> Task { get; private set; }
private async Task<T> Execute(Task<T> task)
{
var result = await task;
Close();
return result;
}
}
用法:
var form = new Form1<int>("Hello", Task.Delay(1000).ContinueWith(_ => 1));
form.Show();
var returnValue = await form.Task;
Console.WriteLine(returnValue);