簡體   English   中英

Observable.Using處理其他線程而不是在

[英]Observable.Using disposes on other thread than created on

我有一個ASP.NET WebApi請求方法,該方法反過來使用Observable.Using在舊版資源上啟動異步調用。 此資源將產生一個新線程,在該線程上引發事件,然后將事件轉換為資源周圍的包裝程序公開的IObservable流中的OnNext項目。

我正在使用IObservable.FirstOrDefaultAsync() await流的結果,並且我的WebApi方法被標記為async

如果我使用這個設置,我會聲名狼藉

異步模塊或處理程序在異步操作仍掛起的同時完成

所以,我的第一個問題是關於此的。 我想得到這個是因為遺留資源產生了新的異步操作(沒有async / await ),但是ASP.NET到底是怎么知道的呢? 已經注冊了什么? 我發現ASP.NET正在查看SynchronizationContext.Current._state.VoidAsyncOutstandingOperationCount來引發此異常,但是哪個調用會遞增此屬性? 線程排隊到ThreadPool? 我相當確定這是由舊資源造成的。

現在,當我處理資源時,為什么這些操作仍然進行? 好吧,似乎Dispose運行在傳播事件的線程上,其概念類似於以下代碼片段。

Observable
    .Using(
        () => {
            Console.WriteLine($"Created on thread: {Thread.CurrentThread.ManagedThreadId}");
            return Disposable.Create(() => {
                Console.WriteLine($"Disposed on thread: {Thread.CurrentThread.ManagedThreadId}");
            });
        },
        _ => Observable.Return(1, NewThreadScheduler.Default))
    .Do(_ => Console.WriteLine($"OnNext on thread: {Thread.CurrentThread.ManagedThreadId}"))
    .Wait();

結果類似於:

Created on thread: 10
OnNext on thread: 11
Disposed on thread: 11

這是設計使然嗎? 當使用using來配置資源時,很明顯,由於代碼是同步的,因此該資源被配置在創建它的同一線程上。 Dispose在單獨的線程上運行時,調用代碼將繼續運行,並且控制器將在Dispose完全完成之前(至少在大多數情況下)返回。

我該如何以合理的方式緩解這種情況? 似乎可行的一種方法是,不使用Observable.Using ,而是使用返回給控制器的此構造,使用FirstOrDefaultAsync() await它:

var resource = // Creating resource manually.
return resource.StartAsyncOperation() // <- observable producing events
    .ObserveOn(SynchronizationContext.Current)
    .Do(_ => resource.Dispose());

不過,這對我來說就像是駭客。

有什么想法和建議嗎?

編輯1

我想我在這里面臨的問題之一是,當我使用Observable.Using在序列終止/完成之后調用資源的Dispose方法。 應該是這樣嗎? 在那種情況下,實際上沒有辦法等待使用該構造的Dispose 我必須使用其他IObservable<Unit> Disposed()方法或類似方法來修改api ...

Dispose將在調用它的線程上調用(嗯)。 更有用的是,在另一個線程上消耗/觀察Rx序列時,將在該線程上調用OnComplete回調。 如果將Rx與標准運算符一起使用,則當序列終止時(使用OnErrorOnComplete ),您將獲得自動處置行為。 自動處理將僅在OnComplete / OnError之后立即發生,並且將在同一線程上運行。

如果您希望將處置綁定到調度程序,則建議查看System.Reactive.Disposables.ScheduledDisposable類型。 但是,似乎在這里使用SynchronizationContext更自然,因此在這種情況下, System.Reactive.Disposables.ContextDisposable可能更合適。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM