我仍然对C#WPF很新鲜,并且一直在使用异步功能。这就是我所拥有的
private void btnGetAccount(object sender, RoutedEventArgs e) {
try {
var found = Task<bool>.Factory.StartNew(() => SearchForAccount());
await found;
}
catch ....
}
和
private bool SearchForAccount() {
Dispatcher.Invoke(() => { //UI Updates }
AnotherFunctionCall();
return true;
}
问题是,有时SearchForAccount函数会超时。因为没有错误被抛出,我还没有弄明白是什么导致了它。我想实现一个允许此函数调用取消的按钮。我已经尝试过使用CancellationTokenSource,但它似乎并没有按照我的方式工作。
非常感谢任何帮助或建议。
谢谢! RealityShift
编辑:
这是我尝试使用CancellationToken
private void btnGetAccount(object sender, RoutedEventArgs e) {
CancellationTokenSource cts = new CancellationTokenSource();
try {
cts.CancelAfter(200);
var found = Task<bool>.Factory.StartNew(() => SearchForAccount(), cts.Token);
await found;
}
catch (OperationCanceledException ex) {
SetStatusLabel("Cancel done.");
}
}
我也试过这样的事情(不能完全记住,现在还没有撤消历史记录):
private void btnGetAccount(object sender, RoutedEventArgs e) {
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken token = cts.Token;
try {
cts.CancelAfter(200);
var found = Task<bool>.Factory.StartNew(() => SearchForAccount(token), cts.Token);
await found;
}
catch (OperationCanceledException ex) {
SetStatusLabel("Cancel done.");
}
}
我将令牌传递给了该功能,但我不记得我对该功能做了什么。在这两种情况下,在SearchForAccount函数调用返回之后(如果它返回),取消没有任何反应。如果它没有返回,那么它就会卡住,这正是我想要取消按钮的原因。
快速破败: 计划启动。 用户可以输入用户名并点击搜索。 然后,搜索将搜索域中是否存在该帐户以及该帐户的一些详细信息。 搜索完成后,结果将发布到数据网格。
问题: 在进行搜索时,有时(很少)它将继续无限期搜索并且永远不会返回。返回超时消息的东西会很棒。
答案 0 :(得分:0)
我只知道如何取消执行Task
。可能会有所帮助。
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken token = cts.Token;
Task myTask = Task.Factory.StartNew(() =>
{
while (true)
{
token.ThrowIfCancellationRequested();
// loop's body
}
}, token);
// cancellation
cts.Cancel();
或
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken token = cts.Token;
Task myTask = Task.Factory.StartNew(() =>
{
while (true)
{
if(token.IsCancellationRequested)
{
return;
}
// loop's body
}
}, token);
// cancellation
cancelToken.Cancel(false);
执行模式如下所示:
//property of the class
private readonly CancellationTokenSource cts = new CancellationTokenSource();
private void btnDo(object sender, RoutedEventArgs e) {
var found = Task.Factory.StartNew(() =>
{
try
{
while (true)
{
cts.Token.ThrowIfCancellationRequested();
//loop's body
}
}
catch (OperationCanceledException ex)
{
SetStatusLabel("Cancel done.");
}
}, cts.Token);
}
private void btnCancel(object sender, RoutedEventArgs e) {
//cancelling
cts.Cancel();
}
答案 1 :(得分:0)
您应该分离获取数据和更新UI的逻辑,在您使用调度程序调用时,您正在冻结UI线程。使用更类似的东西。
private CancellationTokenSource cts;
private void btnGetAccount(object sender, RoutedEventArgs e)
{
try
{
if (cts != null)
{
cts.Cancel();
}
cts = new CancellationTokenSource();
var token = cts.Token;
Task.Factory.StartNew(
() =>
{
var found = SearchForAccount();
if (!token.IsCancellationRequested)
{
Dispatcher.Invoke(
() =>
{
SetStatusLabel(found ? "Found" : "Not found");
});
}
},
token);
}
catch (OperationCanceledException ex)
{
SetStatusLabel("Cancel done.");
}
}