需要在c#中同步控制事件处理程序的帮助

时间:2015-08-18 06:24:58

标签: c# multithreading lambda delegates sync

我有一个代码段如下:

public void PopulateItemList()
{
   foreach(var item in collection)
   {
       bool isSuccess = GetSubItem(item.Id);
       if(!isSuccess)
       {
           ShowError();
           break;
       }
   }
}

public bool GetSubItem(string parentId)
{
    bool isSuccess = false;
    _service.Communication<ViewModel, Request, Response>((ViewModel vm, ref Request) => 
   {
       request.ApiName = Const.FXXXName;
       request.Id = parentId;
   }, (viewModel, response, error) =>
   {
       DoSomething();
       ...
       isSuccess = response.IsOk;   // I put a breakpoint here
   }
   return isSuccess;   // I also put a breakpoint here
}

通讯功能的原型如下:

public void Communication<VM, S, R>(WebSocketOut<VM, S) send, WebSocketIn<VM, R> recv)

WebSocketIn和WebSocketOut是两个委托。问题是当我调试程序时,&#34; return isSuccess;&#34;语句总是在收到来自&#34; response.IsOk&#34;的结果之前运行。所以该func的返回值总是&#34; false&#34;。换句话说,执行顺序是:

  1. return isSuccess
  2. isSuccess = response.IsOk(在MessageReceived(WebSocket4Net)事件被触发后)
  3. 我不知道如何让它以相反的顺序运行。任何建议,建议或帮助将不胜感激。

    由于

2 个答案:

答案 0 :(得分:3)

您可以使用async/awaitTaskCompletionSource

async public void PopulateItemList() //!!async keyword
{
   foreach(var item in collection)
   {
       bool isSuccess = await GetSubItem(item.Id); //!!await
       if(!isSuccess)
       {
           ShowError();
           break;
       }
   }
}

public Task<bool> GetSubItem(string parentId)
{
    var tcs = new TaskCompletionSource<bool>(); //!!
    _service.Communication<ViewModel, Request, Response>((ViewModel vm, ref Request) => 
   {
       request.ApiName = Const.FXXXName;
       request.Id = parentId;
   }, (viewModel, response, error) =>
   {
       DoSomething();
       ...
       tcs.SetResult(response.IsOk); //!!
   }
   return tcs.Task;
}

答案 1 :(得分:1)

尝试使用AutoResetEvent等待异步功能完成。

public bool GetSubItem(string parentId)
{
    System.Threading.AutoResetEvent autoEvent = new System.Threading.AutoResetEvent(false);

    bool isSuccess = false;

    ThreadPool.QueueUserWorkItem((o) =>
    {
        _service.Communication<ViewModel, Request, Response>((ViewModel vm, ref Request) => 
       {
           request.ApiName = Const.FXXXName;
           request.Id = parentId;
       }, (viewModel, response, error) =>
       {
           DoSomething();
           ...
           isSuccess = response.IsOk;   // I put a breakpoint here
           autoEvent.Set();
       }
   });
   autoEvent.WaitOne();
   return isSuccess;   // I also put a breakpoint here
}