簡體   English   中英

如何將輪詢系統轉換為Rx.Net IObservable?

[英]How do I turn a polling system into an Rx.Net IObservable?

我有一個游戲(基於MonoGame / XNA)和更新方法,如下所示:

public void Update(GameTime gameTime)
{
    component.Update(gameTime);
}

我想將其轉換為Reactive模式。 我目前的解決方案是:

public void Initialize()
{
    updateSubject = new Subject<GameTime>();

    component = new Component();

    updateSubject.Subscribe((gameTime) => component.Update(gameTime));
}

public void Update(GameTime gameTime)
{
    updateSubject.OnNext(gameTime);
}

我是Rx的新手,所以我仍然在學習最好的做事方式。 我讀到應該避免使用Subject而應該使用Observable.Create

這里的Subject是否合適?

在這種情況下我怎么能使用Observable.Create

您在這里遇到的關鍵問題是您需要一個可觀察源。 通常,您可以從事件,委托,任務,許多可觀察擴展(如.Interval.Generate )和主題等各種來源創建可觀察對象。

在您的情況下,您必須擁有一個源代碼,您可以擁有代碼,在您的observable外部,將值推送到。 在這種情況下,主題完全沒問題,但您也可以使用代理。

如果您使用主題,那么您的代碼就可以了。 唯一的缺點是你可以調用updateSubject.OnCompleted並完成observable。

如果您想使用委托,那么您的代碼可能如下所示:

private Action<GameTime> updateGameTime = null;

public void Initialize()
{
    component = new Component();

    Observable
        .FromEvent<GameTime>(a => updateGameTime += a, a => updateGameTime -= a)
        .Subscribe((gameTime) => component.Update(gameTime));
}

public void Update(GameTime gameTime)
{
    updateGameTime(gameTime);
}

通過這種方式,你可以用updateGameTime做的唯一事情是傳入一個新的GameTime - 你不能“意外地”結束序列。

現在使用主題與Observable.Create的整個問題是狀態之一。 在您的代碼中,您需要狀態,因此主題是可以的。 通常,盡管如此,建議封裝狀態 - 這就是Observable.Create為您所做的事情。

舉個例子:

var i = -1;
var query =
    Observable
        .Range(0, 10).Select(x =>
        {
            i = -i * 2;
            return x * i;
        });

如果我訂閱這個可觀察的兩次,我得到這兩個序列:

(1)

0 
-4 
16 
-48 
128 
-320 
768 
-1792 
4096 
-9216

(2)

0 
-4096 
16384 
-49152 
131072 
-327680 
786432 
-1835008 
4194304 
-9437184

序列發生變化,因為我使用了狀態(即var i = -1; )。

如果我用Observable.Create編寫代碼,我可以避免這種狀態:

var query =
    Observable
        .Create<int>(o =>
        {
            var i = -1;
            return
                Observable
                .Range(0, 10).Select(x =>
                {
                    i = -i * 2;
                    return x * i;
                })
                .Subscribe(o);
        });

它仍然是相同的查詢,但狀態是封裝的,所以如果我現在訂閱兩次,我得到:

(1)

0 
-4 
16 
-48 
128 
-320 
768 
-1792 
4096 
-9216

(2)

0 
-4 
16 
-48 
128 
-320 
768 
-1792 
4096 
-9216

有時編寫復雜的查詢時,您可能會認為使用主題會使其變得更容易,而且通常情況下,這就是錯誤發生的地方。 在這種情況下,在使用主題之前,您應該總是嘗試找到純運算符方法。 如果你不能在Observable.Create封裝主題的使用。

像你這樣的時候使用主題很好,因為你需要那個外部狀態。

只是指出你代碼unnessecarily使用Rx。

public void Initialize()
{
    //updateSubject = new Subject<GameTime>();

    component = new Component();

    //updateSubject.Subscribe((gameTime) => component.Update(gameTime));
}

public void Update(GameTime gameTime)
{
    //updateSubject.OnNext(gameTime);
    component.Update(gameTime)
}

在這里,我刪除了Subject並直接調用componentUpdate方法,以說明這一點。

也許你正在尋找私人投票方法? 在這種情況下, Observable.Interval可能是一個很好的起點。

暫無
暫無

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

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