如何取消 IMvxAsyncCommand?
How to cancel IMvxAsyncCommand?
我刚开始在 MVVMcross 平台上使用 xamarin android。我需要取消 IMvxAsyncCommand 但我尝试了很多方法,它仍然不起作用。有人对此有任何想法或样本吗?
所以基本上 IMvxAsyncCommand
就像这样调用 Task
:
MyCommand = new MvxAsyncCommand(MyTask);
...
private async Task MyTask()
{
// do async stuff
}
为了取消 Task
,您需要使用 CancellationToken
,您可以从 CancellationTokenSource
获取它并使用另一个命令或任何您想调用 Cancel()
在 CancellationTokenSource
上,所以您可以这样做的一种方法是:
public class MyClass
{
private CancellationTokenSource cts;
public MyClass()
{
MyAsyncCommand = new MvxAsyncCommand(MyTask);
CancelMyTaskCommand = new MvxCommand(() => cts.Cancel());
}
public ICommand MyAsyncCommand {get; private set; }
public ICommand CancelMyTaskCommand { get; private set; }
private async Task MyTask()
{
cts = new CancellationTokenSource();
await MyAsyncStuff(cts.CancellationToken);
cts.Dispose();
cts = null;
}
private async Task MyAsyncStuff(CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
await foo.BlablaAsync();
cancellationToken.ThrowIfCancellationRequested();
await bar.WhateverAsync();
cancellationToken.ThrowIfCancellationRequested();
await foo2.AnotherAsync();
}
}
然后您可以改进代码以避免重复调用 Task
、处理取消异常、使用 MvxNotifyTask 和许多其他东西,但这是基础。
您实际上可以直接取消 MvxAsyncCommand
而无需创建任何额外的 CancellationTokenSource
。
只需对对象本身调用 Cancel()
。
因此,不要让 属性 成为 ICommand
或 IMvxCommand
,而是使用 MvxAsyncCommand
或 IMvxAsyncCommand
。
这样,当您在 Task
中将 CancellationToken
作为参数并在命令中调用 Cancel()
时,它将取消该标记。
private async Task MyAsyncStuff(CancellationToken ct)
{
await abc.AwesomeAsyncMethod(ct);
// and/or
ct.ThrowIfCancellationRequested();
}
所以如果你修改@fmaccaroni 的答案,你会得到这个:
public class MyClass
{
public MyClass()
{
MyAsyncCommand = new MvxAsyncCommand(MyAsyncStuff);
CancelMyTaskCommand = new MvxCommand(() => MyAsyncCommand.Cancel());
}
public IMvxAsyncCommand MyAsyncCommand {get; private set; }
public ICommand CancelMyTaskCommand { get; private set; }
private async Task MyAsyncStuff(CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
await foo.BlablaAsync();
cancellationToken.ThrowIfCancellationRequested();
await bar.WhateverAsync();
cancellationToken.ThrowIfCancellationRequested();
await foo2.AnotherAsync();
}
}
编辑:如果您的异步方法还允许传递 CancellationToken
直接取消它们,甚至更好,MyAsyncStuff
方法可以这样写:
private async Task MyAsyncStuff(CancellationToken cancellationToken)
{
await foo.BlablaAsync(cancellationToken);
await bar.WhateverAsync(cancellationToken);
await foo2.AnotherAsync(cancellationToken);
}
或者,如果您不关心他们开始和完成的顺序:
private Task MyAsyncStuff(CancellationToken cancellationToken)
{
return Task.WhenAll(
foo.BlablaAsync(cancellationToken),
bar.WhateverAsync(cancellationToken),
foo2.AnotherAsync(cancellationToken));
}
我刚开始在 MVVMcross 平台上使用 xamarin android。我需要取消 IMvxAsyncCommand 但我尝试了很多方法,它仍然不起作用。有人对此有任何想法或样本吗?
所以基本上 IMvxAsyncCommand
就像这样调用 Task
:
MyCommand = new MvxAsyncCommand(MyTask);
...
private async Task MyTask()
{
// do async stuff
}
为了取消 Task
,您需要使用 CancellationToken
,您可以从 CancellationTokenSource
获取它并使用另一个命令或任何您想调用 Cancel()
在 CancellationTokenSource
上,所以您可以这样做的一种方法是:
public class MyClass
{
private CancellationTokenSource cts;
public MyClass()
{
MyAsyncCommand = new MvxAsyncCommand(MyTask);
CancelMyTaskCommand = new MvxCommand(() => cts.Cancel());
}
public ICommand MyAsyncCommand {get; private set; }
public ICommand CancelMyTaskCommand { get; private set; }
private async Task MyTask()
{
cts = new CancellationTokenSource();
await MyAsyncStuff(cts.CancellationToken);
cts.Dispose();
cts = null;
}
private async Task MyAsyncStuff(CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
await foo.BlablaAsync();
cancellationToken.ThrowIfCancellationRequested();
await bar.WhateverAsync();
cancellationToken.ThrowIfCancellationRequested();
await foo2.AnotherAsync();
}
}
然后您可以改进代码以避免重复调用 Task
、处理取消异常、使用 MvxNotifyTask 和许多其他东西,但这是基础。
您实际上可以直接取消 MvxAsyncCommand
而无需创建任何额外的 CancellationTokenSource
。
只需对对象本身调用 Cancel()
。
因此,不要让 属性 成为 ICommand
或 IMvxCommand
,而是使用 MvxAsyncCommand
或 IMvxAsyncCommand
。
这样,当您在 Task
中将 CancellationToken
作为参数并在命令中调用 Cancel()
时,它将取消该标记。
private async Task MyAsyncStuff(CancellationToken ct)
{
await abc.AwesomeAsyncMethod(ct);
// and/or
ct.ThrowIfCancellationRequested();
}
所以如果你修改@fmaccaroni 的答案,你会得到这个:
public class MyClass
{
public MyClass()
{
MyAsyncCommand = new MvxAsyncCommand(MyAsyncStuff);
CancelMyTaskCommand = new MvxCommand(() => MyAsyncCommand.Cancel());
}
public IMvxAsyncCommand MyAsyncCommand {get; private set; }
public ICommand CancelMyTaskCommand { get; private set; }
private async Task MyAsyncStuff(CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
await foo.BlablaAsync();
cancellationToken.ThrowIfCancellationRequested();
await bar.WhateverAsync();
cancellationToken.ThrowIfCancellationRequested();
await foo2.AnotherAsync();
}
}
编辑:如果您的异步方法还允许传递 CancellationToken
直接取消它们,甚至更好,MyAsyncStuff
方法可以这样写:
private async Task MyAsyncStuff(CancellationToken cancellationToken)
{
await foo.BlablaAsync(cancellationToken);
await bar.WhateverAsync(cancellationToken);
await foo2.AnotherAsync(cancellationToken);
}
或者,如果您不关心他们开始和完成的顺序:
private Task MyAsyncStuff(CancellationToken cancellationToken)
{
return Task.WhenAll(
foo.BlablaAsync(cancellationToken),
bar.WhateverAsync(cancellationToken),
foo2.AnotherAsync(cancellationToken));
}