2015-08-18 17 views
2

我有如下的代码片段:需要帮助的同步控制事件处理程序在C#中

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两个代表。问题是当我调试程序时,“return isSuccess;”语句总是在从“response.IsOk”收到结果之前运行,因此该func的返回值始终为“false”。换句话说,执行的顺序是:

  1. 回报isSuccess
  2. isSuccess = response.IsOk(之后的messageReceived(WebSocket4Net)触发的事件)

我不知道如何使它以相反的顺序运行。任何意见,建议或帮助将不胜感激。

感谢

+0

您没有关闭_service.Communication'的括号。无效。 –

回答

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; 
} 
+0

是不是'tcs.Task'是一个错字?它不应该是'return tcs.Task;' – Bauss

+1

@Bauss当然,我纠正它。 – Eser

+1

@Eser我通过使用您的解决方案解决了问题。非常感谢。 –

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 
} 
+0

@决定如何_service.Communication是实施这可能会导致死锁 – Eser

+0

@Eser是的,你是正确的,但这只会表明,这种方法的实施必须纠正... – Fabjan

+0

@daniel我试图作为你的答案,但它导致程序将无限期地等待因为Set()和WaitOne()在同一个线程上被调用。无论如何,感谢您的帮助。 –