Gegeben eine SynchronizationContext
, die ich bereits habe (und ist im Grunde ein Fenster zu einem bestimmten Thread), wie erstelle ich Task
s, die zu diesem Kontext gepostet werden?Wie erstelle ich Aufgaben, die an einen bestimmten SynchronizationContext gesendet werden?
Als Referenz ist hier eine sehr einfache Demonstration, wie die SynchronizationContext
eingerichtet ist. Diese
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;
}
}
funktioniert gut für async/ erwartet, die bereits im Rahmen ausgeführt wird.
Jetzt möchte ich in der Lage sein, Task
s von einem externen Zusammenhang (z. B. von einem UI-Thread) zu senden, aber kann nicht scheinen, einen sauberen Weg zu finden, dies zu tun.
Ein Weg, dies zu tun ist mit 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;
});
aber dies ist das Rad und einen großen Schmerz neu zu erfinden Unterstützung Variationen wie StartNew(Func<TResult>)
, StartNew(Func<Task<TResult>>)
usw.
A TaskFactory
Schnittstelle zum SynchronizationContext
wahrscheinlich ideal ist, aber ich kann nicht scheinen, eine zu instanziiert sauber:
TaskFactory CreateTaskFactory()
{
var original = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(SomeDispatcher); // yuck!
try
{
return new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext());
}
finally
{
SynchronizationContext.SetSynchronizationContext(original);
}
}
(dh auf temporären Schlauch Mit Synchronisationskontext des aktuellen Thread scheint hacky.)
Was ist mit der Implementierung von benutzerdefinierten TaskScheduler durch Kopieren der Logik des vorhandenen SynchronizationContextTaskScheduler? Das Kopieren ist natürlich nicht erforderlich, die Logik selbst sieht ziemlich einfach aus. – Evk
@Evk Es gibt ein paar "interne", die Sie nicht benutzen können, aber die Hauptidee ist immer noch da - Sie brauchen Ihren eigenen 'TaskScheduler'. – Luaan
Warum möchten Sie eine Aufgabe im Synchronisationskontext posten? Die übliche Verwendung von Synchronisationskontexten beginnt im Synchronisationskontext. –