2016-09-23 23 views
1

我已經實現了基於Timer的輪詢工作。舉例來說,你可以在客戶端考慮TryConnect - 我打電話TryConnect,它最終會在一段時間內連接。它處理多個線程,如果連接正在處理中,所有後續的TryConnect都會立即返回而不需要任何額外的操作。在內部,我簡單地創建一個計時器,並在間隔期間嘗試連接 - 如果連接失敗,我再試一次。等等。如何將時基輪詢與可等待的任務結合起來

小缺點是它是「火&忘記」的格局,現在我想將其聯合「異步/等待」的格局,即不是調用:

client.TryConnect(); // returns immediately 
// cannot tell if I am connected at this point 

我想這樣稱呼它:

await client.TryConnect(); 
// I am connected for sure 

如何更改我的實現以支持「async/await」?我在想創建空Task(只是await),然後用FromResult完成它,但這種方法創建一個新的任務,不完成給定的實例。

根據記錄,當前的實現看起來像這樣(只是一個代碼的草圖):

public void TryConnect() 
{ 
    if (this.timer!=null) 
    { 
    this.timer = new Timer(_ => tryConnect(),null,-1,-1); 
    this.timer.Change(0,-1); 
    } 
} 
private void tryConnect() 
{ 
    if (/*connection failed*/) 
    this.timer.Change(interval,-1); 
    else 
    this.timer = null; 
} 
+0

如何連接本身來實現?它使用任何異步函數? – YuvShap

+0

你想通過這樣做來達到什麼目的? – usr

回答

1

缺乏良好的Minimal, Complete, and Verifiable code example這是不可能提供任何具體的建議。鑑於你寫了什麼,它是可能你在找什麼是TaskCompletionSource。例如:

private TaskCompletionSource<bool> _tcs; 

public async Task TryConnect() 
{ 
    if (/* no connection exists */) 
    { 
    if (_tcs == null) 
    { 
     this.timer = new Timer(_ => tryConnect(),null,-1,-1); 
     this.timer.Change(0,-1); 
     _tcs = new TaskCompletionSource<bool>(); 
    } 

    await _tcs.Task; 
    } 
} 

private void tryConnect() 
{ 
    if (/*connection failed*/) 
    this.timer.Change(interval,-1); 
    else 
    { 
    _tcs.SetResult(true); 
    _tcs = null; 
    this.timer = null; 
    } 
} 

注:

  • 你原來的代碼示例將重試,如果TryConnect()是連接後再次調用連接邏輯。我希望你真正想要的是檢查是否存在有效的連接,所以我稍微修改了上面的內容來檢查。如果您確實總想嘗試新的連接,即使已經存在,也可以刪除該部分。
  • 代碼設置設置它的結果後_tcsnull立竿見影。但是請注意,任何代碼等待或以其他方式存儲爲_tcs對象將隱含地引用當前_tcs對象Task值,所以它不是一個問題,這裏丟棄場的參考。
  • 沒有非通用TaskCompletionSource。因此,對於情況下,您只需要一個Task,你可以使用泛型類型的佔位符的類型,比如bool我在這裏或object或什麼的來完成。我可以調用SetResult(false),就像SetResult(true)一樣,在這個例子中並不重要。重要的是Task已完成,而不是返回什麼值。上述
  • 的使用async關鍵字使TryConnect()異步方法。恕我直言,這是一個更具可讀性,但當然會產生額外Task代表該方法的操作的輕微開銷。如果你願意,你可以做同樣的事情沒有直接的方法async
public Task TryConnect() 
{ 
    if (/* no connection exists */) 
    { 
    if (_tcs == null) 
    { 
     this.timer = new Timer(_ => tryConnect(),null,-1,-1); 
     this.timer.Change(0,-1); 
     _tcs = new TaskCompletionSource<bool>(); 
    } 

    return _tcs.Task; 
    } 

    return Task.CompletedTask; 
} 
+0

'TaskCompletionSource'是我所需要的,可惜我不知道這個類的存在 - 直到現在:-),非常感謝你的幫助! – astrowalker