[英]ICommand Execute() Task.ContinueWith()
In the Execute()
of a class that implements ICommand
in a WPF application, I have an external call to a method which returns a Task
在WPF应用程序中实现
ICommand
的类的Execute()
中,我对一个返回Task
的方法进行了外部调用
ICommand Class: ICommand类:
public static void Execute(object parameter)
{
Cancel(arg1, arg2);
}
private static void Cancel(IList<object> arg1, object arg2)
{
Task<object> cancelTask = service.AmendAsync
(
CancelTokenSource.Token,
object arg2
);
ProcessCancellingResponse(arg1, arg2);
}
private static void ProcessCancellingResponse(IList<object> arg1, Task<object> cancelTask)
{
cancelTask.ContinueWith
(
task =>
{
Update(task.Result.Response);
},
CancelTokenSource.Token,
TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.OnlyOnRanToCompletion,
TaskScheduler.FromCurrentSynchronizationContext()
);
}
Service Class: 服务类别:
public Task<object> AmendAsync(CancellationToken cancellationToken, object arg1)
{
return Task<object>.Factory.StartNew
(
() =>
{
...
},
cancellationToken,
TaskCreationOptions.None,
TaskScheduler.Default
);
}
My questions are 我的问题是
cancelTask.ContinueWith()
wait on the UI thread or on a background thread? cancelTask.ContinueWith()
在UI线程或后台线程上等待吗? ie if the Task
takes a long time and it is waiting on the UI thread, the UI might freeze. Task
需要很长时间并且它在UI线程上等待,则UI可能会冻结。 According to Domysee comment, I'll be clear here, the Execute
is always run in the UI thread, but you can do in the callback whatever you want including run a background thread, 根据Domysee的评论,我会在这里清楚,
Execute
总是在UI线程中运行,但你可以在回调中做任何你想做的事情,包括运行后台线程,
About the continuation, if you don't explicit tell him on with thread to continue, it will do its job on TaskScheduler.Current
, else, it will continue on which scheduler you defined. 关于延续,如果你没有明确告诉他继续使用线程,它将在
TaskScheduler.Current
上完成它的工作,否则,它将继续你定义的调度程序。
Anyway consider to use async\\await
with\\out capturing to do a continuation 无论如何,考虑使用
async\\await
和\\ out捕获来进行延续
await Task.Run(() => ).ConfigureAwait(true);
await Task.Run(() => ).ConfigureAwait(false);
Update 更新
According to question update, 根据问题更新,
Execute -> UI thread 执行 - > UI线程
Cancel => UI thread 取消=> UI线程
AmendAsync => background thread AmendAsync =>后台线程
ContinueWith => UI thread (because you write FromCurrentSynchronizationContext
) ContinueWith => UI线程(因为你写了
FromCurrentSynchronizationContext
)
what thread invokes the ICommend Execute() Is it the UI thread?
什么线程调用ICommend Execute()它是UI线程吗?
Yes, it will always be on a UI thread. 是的,它将始终在UI线程上。
Will the cancelTask.ContinueWith() wait on the UI thread or on a background thread?
cancelTask.ContinueWith()会在UI线程或后台线程上等待吗?
ContinueWith
is just a regular method call. ContinueWith
只是一个常规的方法调用。 There's no magic. 没有魔力。 So break it down:
所以打破它:
This: 这个:
private static void ProcessCancellingResponse(IList<object> arg1, Task<object> cancelTask)
{
cancelTask.ContinueWith
(
task =>
{
Update(task.Result.Response);
},
CancelTokenSource.Token,
TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.OnlyOnRanToCompletion,
TaskScheduler.FromCurrentSynchronizationContext()
);
}
is the same as this: 与此相同:
private static void ProcessCancellingResponse(IList<object> arg1, Task<object> cancelTask)
{
Action<Task> continuation = task => { Update(Task.Result.Response); };
var token = CancelTokenSource.Token;
var options = TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.OnlyOnRanToCompletion;
var scheduler = TaskScheduler.FromCurrentSynchronizationContext();
cancelTask.ContinueWith(continuation, token, options, scheduler);
}
Since ProcessCancellingResponse
is called on a UI thread, then scheduler
will be a scheduler that executes its tasks on that UI thread. 由于在UI线程上调用
ProcessCancellingResponse
,因此scheduler
将是在该UI线程上执行其任务的调度程序。 Thus, continuation
will run on that UI thread. 因此,
continuation
将在该UI线程上运行。
On a side note, I see at least one mistake: AttachedToParent
is almost certainly wrong. 另外,我看到至少有一个错误:
AttachedToParent
几乎肯定是错的。 Promise tasks (asynchronous tasks) should almost never be attached tasks. 承诺任务(异步任务)几乎不应该是附加任务。
The implementations could be much cleaner, too: 实现也可以更清洁:
private static async Task ProcessCancellingResponseAsync(IList<object> arg1, Task<object> cancelTask)
{
var result = await cancelTask;
Update(result.Response);
}
public object Amend(CancellationToken cancellationToken, object arg1)
{
...
}
private static void Cancel(IList<object> arg1, object arg2)
{
Task<object> cancelTask = Task.Run(() => service.Amend
(
CancelTokenSource.Token,
object arg2
);
ProcessCancellingResponse(arg1, arg2);
}
ICommand Execute() when called directly from UI runs on Main thread (UI thread). 直接从UI调用的ICommand Execute()在主线程(UI线程)上运行。
It will depend where code is. 它取决于代码的位置。 If it is directly inside the Execute it will run on main thread as well because you are specifying the scheduler to be
TaskScheduler.FromCurrentSynchronizationContext()
. 如果它直接位于Execute中,它也将在主线程上运行,因为您将调度程序指定为
TaskScheduler.FromCurrentSynchronizationContext()
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.