2013-07-25 57 views
3

我被困在正確處理在應用程序退出時使用RX創建的線程。我在Process Explorer中看到,在應用程序關閉後,線程仍在運行,導致IO異常。在應用程序退出時處理RX線程

class Program 
{ 
    static void Main(string[] args) 
    { 
     CompositeDisposable subsriptions = new CompositeDisposable(); 

     subscriptions.Add(Observable.Interval(TimeSpan.FromSeconds(15)) 
       .Subscribe(_ => 
       { 
        getData(); 

       })); 
     Thread.Sleep(TimeSpan.FromSeconds(20));  
      subscriptions.Dispose(); 
     } 
    } 
} 

如果你看看,如果我取消註釋subscription.Dispose(),線程終止沒有得到任何數據。任何幫助,將不勝感激。謝謝

+0

什麼是'的getData 「幹嘛? – JerKimball

+0

它只是從.txt讀取一些值。 – Jim

回答

1

您需要某種延遲subsriptions.Add(...)subscriptions.Dispose()之間。在這之間沒有任何延遲,你的應用程序只需立即訂閱並處理它們,沒有時間讓這些線程完成工作。 (和Thread.Sleep(1000)不起作用,因爲它是訂閱功能裏面,不是主要功能的一部分。)

+0

我看到,我已經移動了Thread.Sleep(20000),並在處理訂閱之前增加了mlsec,但沒有運氣。 – Jim

+1

Thread.Sleep()的使用是邪惡的。看到我的答案。如果您通過ReactiveExtensions和async /使用IObservable一起正確地等待,您可以不使用它。 – bradgonesurfing

1

你正在尋找的模式與此類似

class Program { 

    public string GetData(){ 
     return "Hello"; 
    } 

    public string async GetDataAsync(){ 

     return await Observable 
      .Interval(TimeSpan.FromSeconds(15)) 
      .Take(1) 
      .Select(()=>GetData()); 


    } 

    static void Main(string[]args){ 

     var s = GetDataAsync().Wait(); 
    } 

} 

原因Wait是一個入口點,Main,在這種情況下不能是 ,標記爲asyncWait阻止當前線程,直到任務返回 通過GetDataAsync產生一個值。

還要注意,IObservable與async/await兼容,並且會返回序列產生的最後一個 值。這就是爲什麼我加Take(1),因爲它會產生 只有1個勾號。

另一種方法就是打電話給等候直接上的IObservable在

class Program { 

    public string GetData(){ 
     return "Hello"; 
    } 

    public IObservable<string> GetDataObservable(){ 

     return Observable 
      .Interval(TimeSpan.FromSeconds(15)) 
      .Take(1) 
      .Select(()=>GetData()); 


    } 

    static void Main(string[]args){ 

     var s = GetDataObservable().Wait(); 
    } 

} 
+0

感謝您的廣泛響應,我可以問您如何處理在應用程序關閉之前或之後處理線程?目前,我只是在應用程序關閉時終止進程,但是我擔心在工作時這不是正確的方式嗎? – Jim

+2

你不需要殺死任何線程。線程自動返回到線程池,並且進程將退出。 – bradgonesurfing

+0

你很少需要直接接觸線程我會使用被動擴展和異步/等待框架。我建議做一些研究。一旦你得到它,這是非常酷的東西。 – bradgonesurfing

0

您可以訂閱你的觀察到與CancellationToken將取消基礎任務執行:

static void Main(string[] args) 
{ 
    var cts = new CancellationTokenSource(); 
    Observable. 
     Interval(TimeSpan.FromSeconds(15)). 
     Subscribe(_ => getData(), cts.Token)); 
    cts.CancelAfter(TimeSpan.FromSeconds(20)); 
}