C# MVVM+;WCF异步回调

C# MVVM+;WCF异步回调,c#,wpf,wcf,asynchronous,mvvm,C#,Wpf,Wcf,Asynchronous,Mvvm,我有一个WCF服务(IMyService),我将其包装到一个服务(ICentralService)中,这样我就有了一个可以注入ViewModels的中心服务。这将使我能够在调用WCF服务之前在一个位置更改/添加内容 现在,因为我需要进行异步wcf调用,所以我的viewmodel也需要是异步的。我有一个来自viewmodel的回调,但我的CentralService也有自己的回调来调用End。。。方法 问题:将我的viewmodel回调传递给中央服务中的EndTest方法的最佳方式是什么,以便此E

我有一个WCF服务(IMyService),我将其包装到一个服务(ICentralService)中,这样我就有了一个可以注入ViewModels的中心服务。这将使我能够在调用WCF服务之前在一个位置更改/添加内容

现在,因为我需要进行异步wcf调用,所以我的viewmodel也需要是异步的。我有一个来自viewmodel的回调,但我的CentralService也有自己的回调来调用End。。。方法

问题:将我的viewmodel回调传递给中央服务中的EndTest方法的最佳方式是什么,以便此EndTest方法可以通知viewmodel上的回调

或者有更好的方法? 我可以直接在我的ViewModel中注入IMyService,但是我没有一个中心位置(CentralService),在通过WCF将数据发送到服务器之前,我可以在该位置操作/注入数据

注意:我使用的是.NET4.0,不能使用“wait”,我还使用的是WCF IAsyncResult模型(服务器端)

代码:

[ServiceContract(....)]
public interface IMyService {
    [OperationContract(AsyncPattern = true)]
    IAsyncResult BeginTest(int x, AsyncCallback, object state);

    int EndTest(IAsyncResult result);
}

public interface ICentralService {
    void WorkItAsync(int x, AsyncCallback callback);
}

public class CentralService : ICentralService 
{
    private IMyService _Srv;

    public CentralService(IMyService srv) 
    {
        _Srv = srv;
    }

    public void WorkItAsync(int x, AsyncCallback callback) 
    {
        // callback is the callback from my viewmodel

        _Srv.BeginTest(x, new AsyncCallback(WorkItCompleted));
    }

    private void WorkItCompleted(IAsyncResult r) 
    {
        // ...
        int result = _Srv.EndTest(r);

        // Need to call callback from viewmodel now to notify it is ready.
    }
}


public class SomeViewModel : INotifyPropertyChanged 
{
    private ICentralService _Central;

    public SomeViewModel(ICentralService central) {
        _Central = central;
    }

  private void A() {
    _Central.WorkItAsync(5, new AsyncCallback(B));
  }

  private void B(object test) {
    // do something with the result
  }
}
public void WorkItAsync(int x, AsyncCallback callback) 
{
    TaskCompletionSource<int> tcs1 = new TaskCompletionSource<int>();
    Task<int> t1 = tcs1.Task;

    Task<int>.Factory.StartNew(() => 
    {
        int dataResult = -1;
        _Srv.BeginTest(x, (ar) => { 
            dataResult = _Srv.EndTest(ar);
            tcs1.SetResult(dataResult);
        }, null);

        return dataResult;
    });

    if (callback != null)
        t1.ContinueWith((t) => callback(t));

    return t1;
}
更新: 我已经设法将IMyService包装到ICentralService中,并通过ICentralService将结果从WCF(IMyService)传递到我的viewmodel

第一次尝试/idea,但这并没有将我的“dataResult”值返回到我的viewmodel:

public void WorkItAsync(int x, AsyncCallback callback) 
{
    var task = Task<int>.Factory.StartNew(() => 
    {
        int dataResult = -1;
        _Srv.BeginTest(x, (ar) => { 
            dataResult  = _Srv.EndTest(ar);
        }, null);

        return dataResult ;
    });

    if (callback != null)
        task.ContinueWith((t) => callback(t));

    return task;
}
public void WorkItAsync(int x,异步回调)
{
var task=task.Factory.StartNew(()=>
{
int dataResult=-1;
_Srv.beginest(x,(ar)=>{
数据结果=_Srv.EndTest(ar);
},空);
返回数据结果;
});
if(回调!=null)
task.ContinueWith((t)=>callback(t));
返回任务;
}
第二次尝试(有效):

[ServiceContract(....)]
public interface IMyService {
    [OperationContract(AsyncPattern = true)]
    IAsyncResult BeginTest(int x, AsyncCallback, object state);

    int EndTest(IAsyncResult result);
}

public interface ICentralService {
    void WorkItAsync(int x, AsyncCallback callback);
}

public class CentralService : ICentralService 
{
    private IMyService _Srv;

    public CentralService(IMyService srv) 
    {
        _Srv = srv;
    }

    public void WorkItAsync(int x, AsyncCallback callback) 
    {
        // callback is the callback from my viewmodel

        _Srv.BeginTest(x, new AsyncCallback(WorkItCompleted));
    }

    private void WorkItCompleted(IAsyncResult r) 
    {
        // ...
        int result = _Srv.EndTest(r);

        // Need to call callback from viewmodel now to notify it is ready.
    }
}


public class SomeViewModel : INotifyPropertyChanged 
{
    private ICentralService _Central;

    public SomeViewModel(ICentralService central) {
        _Central = central;
    }

  private void A() {
    _Central.WorkItAsync(5, new AsyncCallback(B));
  }

  private void B(object test) {
    // do something with the result
  }
}
public void WorkItAsync(int x, AsyncCallback callback) 
{
    TaskCompletionSource<int> tcs1 = new TaskCompletionSource<int>();
    Task<int> t1 = tcs1.Task;

    Task<int>.Factory.StartNew(() => 
    {
        int dataResult = -1;
        _Srv.BeginTest(x, (ar) => { 
            dataResult = _Srv.EndTest(ar);
            tcs1.SetResult(dataResult);
        }, null);

        return dataResult;
    });

    if (callback != null)
        t1.ContinueWith((t) => callback(t));

    return t1;
}
public void WorkItAsync(int x,异步回调)
{
TaskCompletionSource tcs1=新的TaskCompletionSource();
任务t1=tcs1.任务;
Task.Factory.StartNew(()=>
{
int dataResult=-1;
_Srv.beginest(x,(ar)=>{
数据结果=_Srv.EndTest(ar);
tcs1.SetResult(数据结果);
},空);
返回数据结果;
});
if(回调!=null)
t1.继续使用((t)=>回调(t));
返回t1;
}
我不确定使用TaskCompletionSource是否是一个好的解决方案,但目前它似乎可以工作。(太糟糕了,我必须返回一个无用的-1数据结果值)。

您可以使用lambdas:

public void WorkItAsync(int x, AsyncCallback callback) 
{
    // callback is the callback from my viewmodel

    _Srv.BeginTest(x, ar=>{
        int result = _Srv.EndTest(ar);
        callback(ar);
    });
}
如果需要,ar将是您的最终结果。您甚至可以并行运行多个请求,因为回调变量将位于每个并行调用的本地作用域中。

您可以使用lambdas:

public void WorkItAsync(int x, AsyncCallback callback) 
{
    // callback is the callback from my viewmodel

    _Srv.BeginTest(x, ar=>{
        int result = _Srv.EndTest(ar);
        callback(ar);
    });
}
如果需要,ar将是您的最终结果。您甚至可以并行运行多个请求,因为回调变量将位于每个并行调用的本地作用域中。

您可以使用lambdas:

public void WorkItAsync(int x, AsyncCallback callback) 
{
    // callback is the callback from my viewmodel

    _Srv.BeginTest(x, ar=>{
        int result = _Srv.EndTest(ar);
        callback(ar);
    });
}
如果需要,ar将是您的最终结果。您甚至可以并行运行多个请求,因为回调变量将位于每个并行调用的本地作用域中。

您可以使用lambdas:

public void WorkItAsync(int x, AsyncCallback callback) 
{
    // callback is the callback from my viewmodel

    _Srv.BeginTest(x, ar=>{
        int result = _Srv.EndTest(ar);
        callback(ar);
    });
}

如果需要,ar将是您的最终结果。您甚至可以并行运行多个请求,因为回调变量将在每个并行调用的本地作用域中。

第二次更新看起来不错,但我认为您现在可以使用它来避免TaskCompletionSource。下面是一个用于FromAsync的示例。我尚未对此进行测试,但该方法可能如下所示:

public interface ICentralService
{
    // Just use .ContinueWith to call a completion method
    Task<int> WorkItAsync(int x);
}

public class CentralService : ICentralService 
{
    private IMyService _Srv;

    public CentralService(IMyService srv) 
    {
        _Srv = srv;
    }

    public Task<int> WorkItAsync(int x) 
    {
        // Callback is handled in ViewModel using ContinueWith
        return Task<int>.Factory.FromAsync(_Src.BeginTest, _Src.EndTest, x);
    }
}

public class SomeViewModel : INotifyPropertyChanged 
{
    private ICentralService _Central;

    public SomeViewModel(ICentralService central)
    {
        _Central = central;
    }

    private void A()
    {
        _Central.WorkItAsync(5)
                .ContinueWith(prevTask =>
                {
                    // Handle or throw exception - change as you see necessary
                    if (prevTask.Exception != null)
                        throw prevTask.Exception;

                    // Do something with the result, call another method, or return it...
                    return prevTask.Result;
                });
    }
}
公共接口ICentralService
{
//只需使用.ContinueWith调用完成方法
任务工作同步(intx);
}
公共类中心服务:ICentralService
{
私人IMY服务;
公共中央服务(IMyService srv)
{
_Srv=Srv;
}
公共任务工作同步(int x)
{
//回调在ViewModel中使用ContinueWith进行处理
返回Task.Factory.fromsync(_Src.BeginTest,_Src.EndTest,x);
}
}
公共类SomeViewModel:INotifyPropertyChanged
{
中环私人ICentralService ;;
公共SomeViewModel(ICentralService central)
{
_中央=中央;
}
私人文件A()
{
_中央工作同步(5)
.ContinueWith(prevTask=>
{
//处理或抛出异常-根据需要进行更改
如果(prevTask.Exception!=null)
抛出prevTask.Exception;
//对结果执行某些操作、调用另一个方法或返回它。。。
返回任务结果;
});
}
}

第二次更新看起来不错,但我认为您现在可以使用它来避免TaskCompletionSource。下面是一个用于FromAsync的示例。我尚未对此进行测试,但该方法可能如下所示:

public interface ICentralService
{
    // Just use .ContinueWith to call a completion method
    Task<int> WorkItAsync(int x);
}

public class CentralService : ICentralService 
{
    private IMyService _Srv;

    public CentralService(IMyService srv) 
    {
        _Srv = srv;
    }

    public Task<int> WorkItAsync(int x) 
    {
        // Callback is handled in ViewModel using ContinueWith
        return Task<int>.Factory.FromAsync(_Src.BeginTest, _Src.EndTest, x);
    }
}

public class SomeViewModel : INotifyPropertyChanged 
{
    private ICentralService _Central;

    public SomeViewModel(ICentralService central)
    {
        _Central = central;
    }

    private void A()
    {
        _Central.WorkItAsync(5)
                .ContinueWith(prevTask =>
                {
                    // Handle or throw exception - change as you see necessary
                    if (prevTask.Exception != null)
                        throw prevTask.Exception;

                    // Do something with the result, call another method, or return it...
                    return prevTask.Result;
                });
    }
}
公共接口ICentralService
{
//只需使用.ContinueWith调用完成方法
任务工作同步(intx);
}
公共类中心服务:ICentralService
{
私人IMY服务;
公共中央服务(IMyService srv)
{
_Srv=Srv;
}
公共任务工作同步(int x)
{
//回调在ViewModel中使用ContinueWith进行处理
返回Task.Factory.fromsync(_Src.BeginTest,_Src.EndTest,x);
}
}
公共类SomeViewModel:INotifyPropertyChanged
{
中环私人ICentralService ;;
公共SomeViewModel(ICentralService central)
{
_中央=中央;
}
私人文件A()
{
_中央工作同步(5)
.ContinueWith(prevTask=>
{
//处理或抛出异常-根据需要进行更改
如果(prevTask.Exception!=null)
抛出prevTask.Exception;
//对结果执行某些操作、调用另一个方法或返回它。。。
返回任务结果;
});
}
}

第二次更新看起来很不错,但我觉得很有趣