2015-05-06 22 views
0

我有一個簡單的過程向API發送請求,等待API返回響應,然後繼續響應此響應。我想避免睡覺的主線程,因爲這將作爲服務運行,我不想阻止啓動/停止。While While Loop定期檢查狀態

有沒有辦法實現這一點與計時器?

我的代碼看起來是這樣的:

string RequestID = api.SendRequest(info); 
DateTime fiveMinutesFromNow = GetFiveMinutesFromNow(); 
ApiResponse response = null; 

while (response != null && now < fiveMinutesFromNow) 
{ 
    ApiResponse check = api.GetResponse(RequestID); 
    if(check.status == "Complete") 
    { 
      response = check; 
      break; 
    }else 
    { 
      //Wait for 3 seconds 
    } 
} 

if(response.status == "Complete") 
{ 
//Continue on 
} 

謝謝!

編輯:這是我使用AutoResetEvent的當前修訂。思考?

class MyClass 
{ 
    private Api _api = new Api(); 
    private ApiResponse _response = new ApiResponse(); 
    private EventWaitHandle _waitHandle = new AutoResetEvent(false); 
    private string _requestID; 
    private readonly Object _criticalSection = new Object(); 

    void DoStuff() 
    { 
     Info info = GetInfo(); 
     _requestID = _api.SendRequest(info); 
     Thread pollingThread = new Thread(PollReutersAPI); 
     pollingThread.isBackground = true; 
     pollingThread.Start(); 

     _waitHandle.Reset(); 
     if (!_waitHandle.WaitOne(300000)) 
     { 
      pollingThread.Abort(); 
     }  

     if(_response.status == "Complete") 
     { 
      //Continue on 
     } 
    } 

    void PollApi() 
    { 
     while(true) 
     { 
       ApiResult check = _api.GetResponse(_requestID); 
       lock(_criticalSection) 
       { 
        if(check.status == "Complete") 
        { 
         _response = check; 
         _waitHandle.Set(); 
         return; 
        } 
        else 
        { 
         Thread.Sleep(3000); 
        } 
       } 
     } 
    } 

} 
+0

不要在啓動/停止線程上執行此操作嗎?如果您在啓動時產生工作線程,則在服務停止時它是否被阻塞無關緊要。 – Will

+0

好點。謝謝。儘管如此,這仍然是我想學習的東西。如果這只是在控制檯應用程序中存在,你會怎麼做呢? – neonScarecrow

+0

大概創建一個System.Threading.Timer等待三秒鐘。你只需要確保這個類的實例被應用程序引用,並且該類持有對Timer的引用,所以GC不會來清理它。或者我會懶惰和等待(Timespan.FromSeconds(3))在互斥體上,阻止當前線程。 – Will

回答

0

嘗試旋轉任務以避免主線程在一起。嘗試是這樣的:

private CancellationTokenSource tokenSource; 
    private string RequestID; 
    ApiResponse response; 

    private void form1_Load(object sender, EventArgs e) 
    { 
     freeUI(); 
    } 

    private void do_stuff() 
    { 
     RequestID = api.SendRequest(info); 
     DateTime fiveMinutesFromNow = GetFiveMinutesFromNow(); 
     response = null; 

     while (response != null && now < fiveMinutesFromNow) 
     { 
      ApiResponse check = api.GetResponse(RequestID); 
      if (check.status == "Complete") 
      { 
       response = check; 
       tokenSource.Cancel(); 
       break; // <-- maybe you could remove this since the task was cancelled? 
      } 
      else 
      { 
       //Wait for 3 seconds 
      } 
     } 

     if (response.status == "Complete") 
     { 
      //Continue on 
     } 
    } 

    private async Task freeUI() 
    { 
     await start_process(); 

     // do other things 
    } 

    private Task start_process() 
    { 
     tokenSource = new CancellationTokenSource(); 
     token = tokenSource.Token; 

     return Task.Factory.StartNew(() => 
     { 
      do_stuff(); 

     }, token); 
    } 

我用這樣的事情重新綁定數據綁定對象或執行,我想用戶界面保持響應大,任務重。由於我沒有你的API我不能測試這個,但它應該工作。