我有一个经典的WinForms应用程序,它与服务器应用程序接口进行异步通信。这是通过异步等待模式实现的。
现在我遇到了一个关于“验证”事件的问题。我们使用此事件进行客户端验证(检查输入是否为空)并设置cancel。如果输入有效,则将输入发送到服务器异步并等待结果。
这就是我的问题。现在,控件表示它是有效的。当回调将cancel事件设置为false时,为时已晚。
下面是我的代码:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public string CustomerName { get; set; }
private async void Button1_Validating(object sender, CancelEventArgs e)
{
if (CustomerName == null)
{
e.Cancel = true;
}
else
{
var isValidAndSaved = await SaveOnServerAsync(CustomerName);
// Here is the Problem: Setting e.Cancel in callback is too late.
if (isValidAndSaved)
{
e.Cancel = false;
}
else
{
e.Cancel = true;
}
}
}
/// <returns>True if the given model was valid and save operation was successfull.</returns>
public async Task<bool> SaveOnServerAsync(string customerName)
{
await Task.Delay(3000); // Send given customerName to server in real app.
return customerName.Contains("%") ? false : true;
}
}在这种情况下,我尝试了经典的编程(synchron),在主线程中‘等待’taks。但是后来我产生了一个死锁。
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public string CustomerName { get; set; } = "3";
private void Button1_Validating(object sender, CancelEventArgs e)
{
if (CustomerName == null)
{
e.Cancel = true;
}
else
{
// Deadlock because MainThread waits for callback.
var isValidAndSaved = SaveOnServerAsync(CustomerName).Result;
if (isValidAndSaved)
{
e.Cancel = false;
}
else
{
e.Cancel = true;
}
}
}
/// <returns>True if the given model was valid and save operation was successfull.</returns>
public async Task<bool> SaveOnServerAsync(string customerName)
{
await Task.Delay(3000); // Send given customerName to server in real app.
return customerName.Contains("%") ? false : true;
}
}有没有人想出一个好的模式?
如果我在等待异步任务之前将Cancel设置为false,那么我的问题将是用户单击被丢弃,并且用户体验是足够的。
发布于 2020-08-11 14:57:09
我找到了一个可行的方法。除第一个任务外,所有其他任务都需要"ConfigureAwait(false)".请参见方法'SaveOnServerAsync'.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public string CustomerName { get; set; } = "3";
private void Button1_Validating(object sender, CancelEventArgs e)
{
if (CustomerName == null)
{
e.Cancel = true;
}
else
{
var isValidAndSaved = SaveOnServerAsync(CustomerName).Result;
if (isValidAndSaved)
{
e.Cancel = false;
}
else
{
e.Cancel = true;
}
}
}
/// <returns>True if the given model was valid and save operation was successfull.</returns>
public async Task<bool> SaveOnServerAsync(string customerName)
{
await Task.Delay(3000)
// The solution is that all deeper Tasks need line below.
.ConfigureAwait(false);
;
return customerName.Contains("%") ? false : true;
}
}我找到了很多关于这个问题的文章。这听起来有点误导了她的概念。
这篇MS文章的图3解释了死锁情况:https://docs.microsoft.com/en-us/archive/msdn-magazine/2013/march/async-await-best-practices-in-asynchronous-programming
https://stackoverflow.com/questions/63278874
复制相似问题