gpt4 book ai didi

c# - 如何创建发布到给定 SynchronizationContext 的任务?

转载 作者:行者123 更新时间:2023-11-30 13:55:03 25 4
gpt4 key购买 nike

给定一个 SynchronizationContext ,我已经有了(并且基本上是特定线程的窗口),我如何创建 Task 发布到此上下文的 s?

作为引用,这里有一个非常基本的演示,演示了 SynchronizationContext 如何已成立。

public class SomeDispatcher : SynchronizationContext
{
SomeDispatcher() {

new Thread(() => {

SynchronizationContext.SetSynchronizationContext(this);

// Dispatching loop (among other things)

}).Start();
}

override void Post(SendOrPostCallback d, object state)
{
// Add (d, state) to a dispatch queue;
}
}

这适用于已经在上下文中运行的async/awaits

现在,我希望能够发布 Task从外部上下文(例如,从 UI 线程)对此进行处理,但似乎找不到一种干净的方法来执行此操作。

一种方法是使用 TaskCompletionSource<> .

Task StartTask(Action action)
{
var tcs = new TaskCompletionSource<object>();
SaidDispatcher.Post(state => {
try
{
action.Invoke();
tcs.SetResult(null);
}
catch (Exception ex)
{
tcs.SetException(ex);
}
});
return tcs.Task;
});

但这是在重新发明轮子,并且支持像 StartNew(Func<TResult>) 这样的变体是一个主要的痛苦。 , StartNew(Func<Task<TResult>>)

A TaskFactory SynchronizationContext 的接口(interface)可能是理想的,但我似乎无法干净地实例化一个:

TaskFactory CreateTaskFactory()
{
var original = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(SomeDispatcher); // yuck!
try
{
return new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext());
}
finally
{
SynchronizationContext.SetSynchronizationContext(original);
}
}

(即必须临时处理当前线程的同步上下文似乎很麻烦。)

最佳答案

似乎默认的 SynchronizationContextTaskScheduler

  1. 内部
  2. 仅适用于当前同步上下文

但它的源代码可用here我们发现它相对简单,所以我们可以尝试推出我们自己的调度程序,如下所示:

public sealed class MySynchronizationContextTaskScheduler : TaskScheduler {
private readonly SynchronizationContext _synchronizationContext;

public MySynchronizationContextTaskScheduler(SynchronizationContext context) {
_synchronizationContext = context;
}

[SecurityCritical]
protected override void QueueTask(Task task) {
_synchronizationContext.Post(PostCallback, task);
}

[SecurityCritical]
protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) {
if (SynchronizationContext.Current == _synchronizationContext) {
return TryExecuteTask(task);
}
else
return false;
}

[SecurityCritical]
protected override IEnumerable<Task> GetScheduledTasks() {
return null;
}

public override Int32 MaximumConcurrencyLevel
{
get { return 1; }
}

private void PostCallback(object obj) {
Task task = (Task) obj;
base.TryExecuteTask(task);
}
}

然后你的 CreateTaskFactory 变成:

TaskFactory CreateTaskFactory() {
return new TaskFactory(new MySynchronizationContextTaskScheduler(SomeDispatcher));
}

然后您创建任务:

var factory = CreateTaskFactory();
var task = factory.StartNew(...);

关于c# - 如何创建发布到给定 SynchronizationContext 的任务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37524483/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com