加载表单后取消异步操作?
Cancel an async operation after the form has loaded?
我有不同的 类(实现接口),其中一种方法是执行异步数据库搜索:
public async void SearchAsync(CancellationToken ct)
{
await Task.Run(() => {Find(); }, ct);
}
private void Find()
{
//do db search here...
}
当打开表单时,会执行后台异步搜索以加快用户输入速度,所以我做的是:
protected override void OnShown(EventArgs e)
{
base.OnShown(e);
try
{
//Get list of items that will perform async search...
//var results = ...
//Do an async search
Task task = Task.Factory.StartNew(() =>
{
foreach (var item in results)
{
item.SearchAsync(cts.Token);
}
}, cts.Token);
}
catch (OperationCanceledException)
{ }
}
以防用户在任务仍在执行时关闭表单,我会这样做:
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
if (cts != null)
{
cts.Cancel();
}
}
首先,以上是执行异步操作的正确方法吗?
其次,当我在任务仍未完成时关闭表单时,代码永远不会到达 OperationCancelException。难道是上面的实现不正确?
有几点需要注意。首先,您正在使用 "async over sync" 反模式,应该强烈避免这种模式。您还传递了 CancellationToken
但实际上从未对其进行监视。如果你的方法是同步的,你不能在执行时真正监控它,你能做的最好的就是在执行 Search
:
的每次迭代之前监控 CancellationToken
public void Search()
{
Find();
}
protected override async void OnShown(EventArgs e)
{
base.OnShown(e);
try
{
await Task.Run(() =>
{
foreach (var item in results)
{
cts.Token.ThrowIfCancellationRequested();
item.Search();
}
}, cts.Token);
}
catch (OperationCanceledException)
{ }
}
然后你取消:
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
if (cts != null)
{
cts.Cancel();
}
}
我有不同的 类(实现接口),其中一种方法是执行异步数据库搜索:
public async void SearchAsync(CancellationToken ct)
{
await Task.Run(() => {Find(); }, ct);
}
private void Find()
{
//do db search here...
}
当打开表单时,会执行后台异步搜索以加快用户输入速度,所以我做的是:
protected override void OnShown(EventArgs e)
{
base.OnShown(e);
try
{
//Get list of items that will perform async search...
//var results = ...
//Do an async search
Task task = Task.Factory.StartNew(() =>
{
foreach (var item in results)
{
item.SearchAsync(cts.Token);
}
}, cts.Token);
}
catch (OperationCanceledException)
{ }
}
以防用户在任务仍在执行时关闭表单,我会这样做:
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
if (cts != null)
{
cts.Cancel();
}
}
首先,以上是执行异步操作的正确方法吗?
其次,当我在任务仍未完成时关闭表单时,代码永远不会到达 OperationCancelException。难道是上面的实现不正确?
有几点需要注意。首先,您正在使用 "async over sync" 反模式,应该强烈避免这种模式。您还传递了 CancellationToken
但实际上从未对其进行监视。如果你的方法是同步的,你不能在执行时真正监控它,你能做的最好的就是在执行 Search
:
CancellationToken
public void Search()
{
Find();
}
protected override async void OnShown(EventArgs e)
{
base.OnShown(e);
try
{
await Task.Run(() =>
{
foreach (var item in results)
{
cts.Token.ThrowIfCancellationRequested();
item.Search();
}
}, cts.Token);
}
catch (OperationCanceledException)
{ }
}
然后你取消:
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
if (cts != null)
{
cts.Cancel();
}
}