Uygulamamın eklentileri ayrı uygulama etki alanlarına yüklemesi ve ardından bunların içeriklerini eşzamansız bir şekilde yürütmesi gerekiyor.Uygulama etki alanı uzaklaştırma ve görevlerini birleştirirken kilitlenme
static class RemoteTask
{
public static async Task<T> ClientComplete<T>(RemoteTask<T> remoteTask,
CancellationToken cancellationToken)
{
T result;
using (cancellationToken.Register(remoteTask.Cancel))
{
RemoteTaskCompletionSource<T> tcs = new RemoteTaskCompletionSource<T>();
remoteTask.Complete(tcs);
result = await tcs.Task;
}
await Task.Yield(); // HACK!!
return result;
}
public static RemoteTask<T> ServerStart<T>(Func<CancellationToken, Task<T>> func)
{
return new RemoteTask<T>(func);
}
}
class RemoteTask<T> : MarshalByRefObject
{
readonly CancellationTokenSource cts = new CancellationTokenSource();
readonly Task<T> task;
internal RemoteTask(Func<CancellationToken, Task<T>> starter)
{
this.task = starter(cts.Token);
}
internal void Complete(RemoteTaskCompletionSource<T> tcs)
{
task.ContinueWith(t =>
{
if (t.IsFaulted)
{
tcs.TrySetException(t.Exception);
}
else if (t.IsCanceled)
{
tcs.TrySetCancelled();
}
else
{
tcs.TrySetResult(t.Result);
}
}, TaskContinuationOptions.ExecuteSynchronously);
}
internal void Cancel()
{
cts.Cancel();
}
}
class RemoteTaskCompletionSource<T> : MarshalByRefObject
{
readonly TaskCompletionSource<T> tcs = new TaskCompletionSource<T>();
public bool TrySetResult(T result) { return tcs.TrySetResult(result); }
public bool TrySetCancelled() { return tcs.TrySetCanceled(); }
public bool TrySetException(Exception ex) { return tcs.TrySetException(ex); }
public Task<T> Task
{
get
{
return tcs.Task;
}
}
}
Sanki kullanılır: Ben marshallable türlerinde Task
sarmak için bazı kodlar yazdım
sealed class ControllerAppDomain
{
PluginAppDomain plugin;
public Task<int> SomethingAsync()
{
return RemoteTask.ClientComplete(plugin.SomethingAsync(), CancellationToken.None);
}
}
sealed class PluginAppDomain : MarshalByRefObject
{
public RemoteTask<int> SomethingAsync()
{
return RemoteTask.ServerStart(async cts =>
{
cts.ThrowIfCancellationRequested();
return 1;
});
}
}
Ama bir engelle çalıştırmak. ClientComplete
'da bakarsanız, eklediğim bir Task.Yield()
var. Bu satırı yorumluyorum, ClientComplete
asla geri dönmeyecek. Herhangi bir fikir?
http://stackoverflow.com/questions/13489065/best-practice-to-call-configureawait-for-all-server-side-code gibi "C# async deadlock ConfigureAwait" için arama sonuçlarını göz önünde bulundurun bir çözüm olurdu. –
Bunu tekrarlayamıyorum. 'ControllerAppDomain.SomethingAsync' hiçbir zaman benim için askıda kalıyor ya da ister bir thread havuz bağlamında isterse tek iş parçacıklı bir bağlamda olsun 'bekle' özelliğini kullanmam. Yukarıdaki kodun sorunu kopyaladığından emin misiniz? –
@StephenCleary Kodu başka bir makinede denedim ve orada da üretemiyorum. İlginç. –