Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用System.Reactive';s扩展_C#_Multithreading_System.reactive_.net 5 - Fatal编程技术网

C# 使用System.Reactive';s扩展

C# 使用System.Reactive';s扩展,c#,multithreading,system.reactive,.net-5,C#,Multithreading,System.reactive,.net 5,下面的代码从Binance从开始日期到结束日期下载历史OHLCV数据。由于Binance允许我们一次只下载1000支蜡烛,所以我按原样下载了Async。如对本规范有任何建议,也将不胜感激 实际的问题是如何使downloadsync多线程化,以加快进程,因为想象一下从2018年到2021年每隔5米下载蜡烛。我更喜欢使用System.Reactive,但我想也欢迎使用其他解决方案,因为很难将代码表示为多线程版本 下面的代码可以测试 使用Binance.Net; 使用Binance.Net.enum;

下面的代码从Binance从开始日期到结束日期下载历史OHLCV数据。由于Binance允许我们一次只下载1000支蜡烛,所以我按原样下载了Async。如对本规范有任何建议,也将不胜感激

实际的问题是如何使
downloadsync
多线程化,以加快进程,因为想象一下从2018年到2021年每隔5米下载蜡烛。我更喜欢使用
System.Reactive
,但我想也欢迎使用其他解决方案,因为很难将代码表示为多线程版本

下面的代码可以测试

使用Binance.Net;
使用Binance.Net.enum;
使用Binance.Net.com接口;
使用Newtonsoft.Json;
使用制度;
使用System.Collections.Generic;
使用System.IO;
使用System.Threading.Tasks;
使用System.Linq;
使用System.Text.RegularExpressions;
使用System.Reactive.Linq;
使用系统线程;
命名空间下载CandleDataTest
{
公共类数据提供者
{
私人交易所;
公共数据提供程序(Exchange)
{
_交换=交换;
}
公共异步任务下载异步(字符串对、KlineInterval间隔、DateTime startDate、DateTime endDate、int startupCandleCount)
{
日期时间开始=开始日期;
DateTime end=endDate;
var tempStartDate=开始;
var tempEndDate=结束;
var templast=新列表();
对于(int i=0;tempStartDate0)
{
//当i>0时,移除第一个蜡烛,以防止重复
如果(i>0)
{
蜡烛。移除(0);
}
var first=蜡烛。first();
var last=蜡烛。last();
WriteLine($“First:{First.Timestamp}| Last:{Last.Timestamp}”);
圣殿骑士。添加范围(蜡烛);
tempStartDate=最后一个时间戳;
}
}
//查找重复项
var groups=templast.GroupBy(g=>g.Timestamp).Where(e=>e.Skip(1.Any());
foreach(组中的var组)
{
控制台写入线(组键);
foreach(组中的var ohclv)
{
Console.WriteLine(“\t”+ohclv.Timestamp);
}
}
返回null;
}
}
班级计划
{
公共静态void StartBackgroundWork()
{
WriteLine(“显示在后台线程上从开始到开始的用法:”;
var o=可观察的。开始(()=>
{
//这从后台线程开始。
WriteLine(“来自后台线程。不阻止主线程”);
Console.WriteLine(“计算…”);
睡眠(3000);
Console.WriteLine(“背景工作已完成”);
}).Finally(()=>Console.WriteLine(“主线程已完成”);
Console.WriteLine(“\r\n\t在主线程中…\r\n”);
o、 Wait();//等待后台操作完成。
}
静态异步任务主(字符串[]args)
{
使用var exchange=new exchange();
var dataProvider=新的数据提供程序(exchange);
wait dataProvider.DownloadAsync(“TRXUSDT”,KlineInterval.5分钟),新日期时间(2019,1,1),新日期时间(2019,1,2,100)。configurewait(false);
Console.ReadLine();
}
}
公共级OHLCV
{
公共日期时间时间戳{get;set;}
公共十进制开放{get;set;}
公共十进制高位{get;set;}
公共十进制低位{get;set;}
公共十进制关闭{get;set;}
公共十进制卷{get;set;}
}
公共静态类扩展
{
公共静态OHLCV待处理(此IBiancekline蜡烛)
{
返回新的OHLCV
{
时间戳=candle.OpenTime,
打开,打开,
高=蜡烛,高,
低=蜡烛,低,
关闭=蜡烛,关闭,
音量=烛光。基本音量,
};
}
}
公共类交换:IDisposable
{
私有只读iBanceClient\u客户端;
公共交换()
{
_client=newbinanceclient();
}
公共异步任务GetCandleAsync(字符串对,KlineInterval间隔,DateTime?startTime=null,DateTime?endTime=null,int?limit=null)
{
var result=await_client.Spot.Market.GetKlinesAsync(对、间隔、开始时间、结束时间、限制)。ConfigureAwait(false);
如果(结果、成功)
{
返回result.Data?.Select(e=>e.toHandle()).ToList();
}
返回null;
}
公共空间处置()
{
如果(_client!=null)
{
_client.Dispose();
}
}
}
}

并行发出更多web请求的关键是创建许多任务,并使用
Task.WhenAll()
等待它们,而不是等待循环中的每个任务


如果您在循环中等待每个线程,它们将按顺序进行处理(尽管在发出web请求时UI线程不会被阻止)。

您严重过度考虑了这一点

由于您得到的蜡烛间隔均匀,并且您知道每次调用
GetKlinesAsync
会得到多少蜡烛,因此您可以计算所需的所有开始日期

    var pair = "TRXUSDT";
    var interval = KlineInterval.FiveMinutes;
    var startDate = new DateTime(2019, 1, 1);
    var endDate = new DateTime(2019, 1, 2);
    var gap = 5.0; // same as `interval` for purpose of computing start dates.
    var limit = 100;

    IObservable<DateTime> startDates =
        Observable
            .Generate(startDate, x => x <= endDate, x => x.AddMinutes(gap * limit), x => x);
这就产生了所有的
    IObservable<OHLCV> query =
        from s in startDates
        from rs in
            Observable
                .Using(
                    () => new BinanceClient(),
                    bc => Observable.FromAsync(ct =>
                        bc.Spot.Market.GetKlinesAsync(pair, interval, s, endDate, limit, ct)))
        where rs.Success
        from c in rs.Data.Select(x => x.ToCandle())
        select c;
    IDisposable subscription =
        query
            .ToArray()
            .Select(xs => xs.OrderBy(x => x.Timestamp).ToArray())
            .Subscribe(cs =>
            {
                /* candles downloaded using multiple threads */
                /* and sorted in `Timestamp` order  */
            });
public async Task<List<OHLCV>> DownloadAsync(string pair, KlineInterval interval, double gap, DateTime startDate, DateTime endDate, int limit)
{
    IObservable<DateTime> startDates =
        Observable
            .Generate(startDate, x => x <= endDate, x => x.AddMinutes(gap * limit), x => x);

    IObservable<OHLCV> query =
        from s in startDates
        from rs in
            Observable
                .Using(
                    () => new BinanceClient(),
                    bc => Observable.FromAsync(ct =>
                        bc.Spot.Market.GetKlinesAsync(pair, interval, s, endDate, limit, ct)))
        where rs.Success
        from c in rs.Data.Select(x => x.ToCandle())
        select c;

    return await query.ToArray().Select(xs => xs.OrderBy(x => x.Timestamp).ToList());
}