![](/img/trans.png)
[英]Error Handling with Observable.Using and Observable.Retry
[英]Handling WebSocket's class close and dispose (Observable.Using)
如何處理WebSocket
的關閉和處置? simple.SubscribeToTicker().Subscribe(...)
也需要處理。
我看到有些人這樣做,但我不確定Observable.Using(...)
的行為以及何時進行處置。
var message =
Observable.Using(() => ws,
_ => Observable.FromEventPattern<MessageReceivedEventArgs>(h => ws.MessageReceived += h,
h => ws.MessageReceived -= h));
using System.Net;
using System.Reactive.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using RestSharp;
using WebSocket4Net;
namespace SimpleTest;
public class Simple
{
public RestPriceTicker24Hr? GetTicker()
{
const string uri = "https://api.binance.com";
var client = new RestClient(uri);
var request = new RestRequest("/api/v3/ticker/24hr?symbol=BNBUSDT", Method.GET);
var response = client.Execute(request);
if (response.StatusCode != HttpStatusCode.OK)
throw new InvalidOperationException();
var content = response.Content;
var deserialize = JsonSerializer.Deserialize<RestPriceTicker24Hr>(content, new JsonSerializerOptions
{
NumberHandling = JsonNumberHandling.AllowReadingFromString
});
return deserialize;
}
public IObservable<PriceTicker24Hr?> SubscribeToTicker()
{
const string uri = "wss://stream.binance.com:9443/ws";
var ws = new WebSocket($"{uri}/bnbusdt@ticker") // TODO: Dispose
{
AutoSendPingInterval = 3, // 3 seconds
EnableAutoSendPing = true
};
ws.Open();
ws.Error += (_, e) => { Console.WriteLine($"Exception: {e.Exception.Message}"); };
ws.Opened += (_, _) => { Console.WriteLine("Connection opened"); };
ws.Closed += (_, _) => { Console.WriteLine("Connection closed"); };
//var message =
// Observable.Using(() => ws,
// _ => Observable.FromEventPattern<MessageReceivedEventArgs>(h => ws.MessageReceived += h,
// h => ws.MessageReceived -= h));
var message =
Observable.FromEventPattern<MessageReceivedEventArgs>(h => ws.MessageReceived += h,
h => ws.MessageReceived -= h);
return message.Select(e =>
JsonSerializer.Deserialize<PriceTicker24Hr>(e.EventArgs.Message, new JsonSerializerOptions
{
NumberHandling = JsonNumberHandling.AllowReadingFromString
}));
}
}
public class Program
{
private static void GetData()
{
var simple = new Simple();
var ticker = simple.GetTicker();
simple.SubscribeToTicker().Subscribe(message => { Console.WriteLine($"Message: {message?.BestAskPrice}"); }); // TODO: Dispose
}
private static void Main()
{
GetData();
Console.ReadKey();
}
}
public class PriceTicker24Hr
{
[JsonPropertyName("e")] public string? EventType { get; set; }
[JsonPropertyName("E")] public long EventTime { get; set; }
[JsonPropertyName("s")] public string? Symbol { get; set; }
[JsonPropertyName("p")] public decimal PriceChange { get; set; }
[JsonPropertyName("P")] public decimal PriceChangePercent { get; set; }
[JsonPropertyName("w")] public decimal WeightedAveragePrice { get; set; }
[JsonPropertyName("x")] public decimal PreviousClosePrice { get; set; }
[JsonPropertyName("c")] public decimal LastPrice { get; set; }
[JsonPropertyName("Q")] public decimal LastQuantity { get; set; }
[JsonPropertyName("b")] public decimal BestBidPrice { get; set; }
[JsonPropertyName("B")] public decimal BestBidQuantity { get; set; }
[JsonPropertyName("a")] public decimal BestAskPrice { get; set; }
[JsonPropertyName("A")] public decimal BestAskQuantity { get; set; }
[JsonPropertyName("o")] public decimal OpenPrice { get; set; }
[JsonPropertyName("h")] public decimal HighPrice { get; set; }
[JsonPropertyName("l")] public decimal LowPrice { get; set; }
[JsonPropertyName("v")] public decimal TotalTradedBaseVolume { get; set; }
[JsonPropertyName("q")] public decimal TotalTradedQuoteVolume { get; set; }
[JsonPropertyName("O")] public long OpenTime { get; set; }
[JsonPropertyName("C")] public long CloseTime { get; set; }
[JsonPropertyName("F")] public long FirstTradeId { get; set; }
[JsonPropertyName("L")] public long LastTradeId { get; set; }
[JsonPropertyName("n")] public long Count { get; set; }
}
public class RestPriceTicker24Hr
{
[JsonPropertyName("symbol")] public string? Symbol { get; set; }
[JsonPropertyName("priceChange")] public decimal PriceChange { get; set; }
[JsonPropertyName("priceChangePercent")]
public decimal PriceChangePercent { get; set; }
[JsonPropertyName("weightedAvgPrice")] public decimal WeightedAveragePrice { get; set; }
[JsonPropertyName("prevClosePrice")] public decimal PreviousClosePrice { get; set; }
[JsonPropertyName("lastPrice")] public decimal LastPrice { get; set; }
[JsonPropertyName("lastQty")] public decimal LastQuantity { get; set; }
[JsonPropertyName("bidPrice")] public decimal BestBidPrice { get; set; }
[JsonPropertyName("bidQty")] public decimal BestBidQuantity { get; set; }
[JsonPropertyName("askPrice")] public decimal BestAskPrice { get; set; }
[JsonPropertyName("askQty")] public decimal BestAskQuantity { get; set; }
[JsonPropertyName("openPrice")] public decimal OpenPrice { get; set; }
[JsonPropertyName("highPrice")] public decimal HighPrice { get; set; }
[JsonPropertyName("lowPrice")] public decimal LowPrice { get; set; }
[JsonPropertyName("volume")] public decimal TotalTradedBaseVolume { get; set; }
[JsonPropertyName("quoteVolume")] public decimal TotalTradedQuoteVolume { get; set; }
[JsonPropertyName("openTime")] public long OpenTime { get; set; }
[JsonPropertyName("closeTime")] public long CloseTime { get; set; }
[JsonPropertyName("firstId")] public long FirstTradeId { get; set; }
[JsonPropertyName("lastId")] public long LastTradeId { get; set; }
[JsonPropertyName("count")] public long Count { get; set; }
}
Every 確實需要在Observable.Using
中,以便在可觀察對象結束時觸發處置。
這就是它的樣子:
public IObservable<PriceTicker24Hr?> SubscribeToTicker() =>
Observable
.Using(
() =>
{
const string uri = "wss://stream.binance.com:9443/ws";
var ws = new WebSocket($"{uri}/bnbusdt@ticker") // TODO: Dispose
{
AutoSendPingInterval = 3, // 3 seconds
EnableAutoSendPing = true
};
ws.Open();
ws.Error += (_, e) => { Console.WriteLine($"Exception: {e.Exception.Message}"); };
ws.Opened += (_, _) => { Console.WriteLine("Connection opened"); };
ws.Closed += (_, _) => { Console.WriteLine("Connection closed"); };
return ws;
},
ws =>
Observable
.FromEventPattern<MessageReceivedEventArgs>(
h => ws.MessageReceived += h,
h => ws.MessageReceived -= h)
.Select(e =>
JsonSerializer.Deserialize<PriceTicker24Hr>(
e.EventArgs.Message,
new JsonSerializerOptions
{
NumberHandling = JsonNumberHandling.AllowReadingFromString
})));
這是一個可測試的示例,可以看到Using
in action:
IObservable<Unit> observable =
Observable
.Using(
() => Disposable.Create(() => Console.WriteLine("Using Disposed!")),
_ => Observable.Never<Unit>());
IDisposable subscription = observable.Subscribe();
subscription.Dispose();
彈出Using Disposed!
在控制台上。
這是另一個例子:
IObservable<int> observable =
Observable
.Using(
() => Disposable.Create(() => Console.WriteLine("Using Disposed!")),
_ => Observable.Repeat(42))
.Take(1);
IDisposable subscription = observable.Subscribe(Console.WriteLine);
彈出以下內容:
42
Using Disposed!
希望這可以幫助您了解Observable.Using
是如何工作的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.