C#, Асинхронные remote вызовы
Я не очень понимаю, чем тебя не устраивают event-ы. Как ты хочешь реализовывать асинхронность без event-ов, инфраструктурой?
Как ты хочешь реализовывать асинхронность без event-оввместо event-ов вполне достаточно простого делегата(лямбды) в аргументе метода. Вот близки к идеальному варианту GWT, из неприятностей остается только дублирование *Async интерфейса.
Вероятно, можно написать простенький helper, который на базе background worker-а делает то, что ты хочешь из синхронного вызова.
Но в тему треда - мне кажется, у MS нет более удобного, чем WCF, подхода.
КОЛЛБЭК!
использование:
RemoteExecuter.Execute(
facade => facade.Method1(1, 2
result => Console.WriteLine(result)
);
реализация:
public static class RemoteExecuter
{
public static void Execute<TResult>(Func<IRemoteFacade, TResult> func, Action<TResult> action)
{
func(ProxyCreator.CreateInterfaceProxy<IRemoteFacade>(new Interceptor<TResult>(action;
}
private class Interceptor<TResult> : IInterceptor
{
private readonly Action<TResult> action;
public Interceptor(Action<TResult> action)
{
this.action = action;
}
public void Intercept(IInvocation invocation)
{
var backgroundWorker = new BackgroundWorker;
backgroundWorker.DoWork +=
(sender, doWorkEventArgs) =>
{
var result = ProcessBytes(SharedUtil.Serialize(new object[] {invocation.Method.Name, invocation.Arguments};
doWorkEventArgs.Result = result == null ? null : SharedUtil.Deserialize(result);
};
backgroundWorker.RunWorkerCompleted +=
(sender, completedEventArgs) => actionTResult) completedEventArgs.Result);
backgroundWorker.RunWorkerAsync;
invocation.ReturnValue = default(TResult);
}
private static byte[] ProcessBytes(byte[] bytes)
{
//здесь пересылаем байты туда и обратно
}
}
}
public static class ProxyCreator
{
public static T CreateInterfaceProxy<T>(IInterceptor interceptor)
{
return Cache<T>.Func(interceptor);
}
private static class Cache<T>
{
public readonly static Func<IInterceptor, T> Func;
static Cache
{
var options = ProxyGenerationOptions.Default;
var type = new DefaultProxyBuilder.CreateInterfaceProxyTypeWithoutTarget(typeof(T new Type[0], options);
Func =
interceptor =>
{
return (T)Activator.CreateInstance(
type,
new List<object>(options.MixinData.Mixins) { new[] { interceptor }, new object }.ToArray;
};
}
}
}
Да, мне бы больше понравилось, если бы была общая сборка с общими типами вместо генерированного кода клиента.Так для этого же есть ChannelFactory<TChannel>.CreateChannel
Так для этого же есть ChannelFactory<TChannel>.CreateChannelя специально же вынес в заголовок "Асинхронные".
Для асинхронных вызовов через ChannelFactory все равно интерфейс кодогенеренный, причем его не удобно использовать: на элементарный вызов пара лишних шагов в том числе каст. Короче, не для людей.
Оставить комментарий
6yrop
Как сейчас на дотнете делают асинхронные remote вызовы между .NET->.NET. То что предлагается в WCF-е – кодогенерация и event-ы — мне не нравится, сильно громоздко, плохо управляемо. Да и вообще с WCF не хочется связываться.Собственно чего хочется. Определяем интерфейс IRemoteFacade, кладем его в сборку, на которую ссылается и сервер и клиент. На сервере делаем его имплементацию RemoteFacadeImpl. А на клиенте дергаем методы интерфейса IRemoteFacade. Удаленные вызовы и асинхронность должны обеспечиваться инфраструктурой.
P.S. да, C# 5.0 еще не вышел.