Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/288.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# 使用计时器获取并行请求_C#_Timer_Parallel.foreach - Fatal编程技术网

C# 使用计时器获取并行请求

C# 使用计时器获取并行请求,c#,timer,parallel.foreach,C#,Timer,Parallel.foreach,我有这个场景。我有一个计时器(autoreset=true),每隔2秒执行一次,当计时器触发时,它将调用10个不同的URL来收集数据。每次平均1秒 我在parallel.foreach循环中运行了这个过程,但是发生的是大多数调用返回得很快,但随机返回的一些调用将花费更长的时间。然后,获取所有10个请求所需的总时间是10秒 下一个事件不会触发,直到并行请求全部完成,计时器才能重试,因此理论上它不是每2秒轮询一次URL public List<string> Urls {get;set;

我有这个场景。我有一个计时器(autoreset=true),每隔2秒执行一次,当计时器触发时,它将调用10个不同的URL来收集数据。每次平均1秒

我在parallel.foreach循环中运行了这个过程,但是发生的是大多数调用返回得很快,但随机返回的一些调用将花费更长的时间。然后,获取所有10个请求所需的总时间是10秒

下一个事件不会触发,直到并行请求全部完成,计时器才能重试,因此理论上它不是每2秒轮询一次URL

public List<string> Urls {get;set;}

private Timer SetupTimer()
    {
        var timer = new Timer(2000);
        timer.AutoReset = false;
        timer.Elapsed += timer_Elapsed;
        timer.Start();
        return timer;
    }

 private async void timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        try
        {
            Parallel.ForEach(Urls, url=>
                {
                    var data= _dataService.GetData(url);
                    SetOnDataRecieved(new DataRecievedEventArgs(data));
                });
        }
        finally
        {
            if (timer == null) return;
            if (!timer.Enabled) { timer.Enabled = true; }
            timer.Start();
        }
    }
公共列表URL{get;set;}
专用定时器SetupTimer()
{
var定时器=新定时器(2000);
timer.AutoReset=false;
timer.appeated+=timer\u appeated;
timer.Start();
返回计时器;
}
专用异步无效计时器(对象发送器,ElapsedEventArgs e)
{
尝试
{
Parallel.ForEach(url,url=>
{
var data=\u dataService.GetData(url);
SetOnDataReceived(新数据ReceiveDeventargs(数据));
});
}
最后
{
if(timer==null)返回;
如果(!timer.Enabled){timer.Enabled=true;}
timer.Start();
}
}

有什么更好的方法来实现这一点?谢谢。

除非所有等待最慢的URL都有问题,否则您的实现本身没有什么问题。您可以实现一个封装所有程序逻辑的类,并且一次只连接到一个URL。这样,没有一个URL会阻止其他URL。将尽可能快地检索每个URL,然后继续两秒钟的等待。类似的方法可能会起作用(未经测试):


你能和我分享一些代码吗,你已经试着让它工作了吗?谢谢,我会尝试一下,希望它能满足我的需要。
public class UrlWatcher
{
    public string Url { get; set; }
    Timer timer { get; set; } = new Timer();
    DataService _dataService { get; set; }
    //Todo: Implement CancellationToken to gracefully stop the timer.

    //Event to report retrieved data
    public EventHandler<DataReceivedEventArgs> OnDataReceived; 

    public UrlWatcher(string Url, int TimerInterval = 2000)
    {
        //Use your implementation of DataService() here
        _dataService = new DataService(); 
        this.Url = Url;
        timer.AutoReset = false;
        timer.Interval = TimerInterval;
    }

    public void Start() // Call this to start polling the URL
    {
        timer.Start();
    }

    public async void timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        try
        {
            var data = await _dataService.GetData(Url);
            OnDataReceived(this, new DataReceivedEventArgs(data));
        }
        finally
        {
            if (timer != null && !timer.Enabled) 
            { 
                timer.Enabled = true;
                timer.Start();
            }
        }
    }
}
    //Thread-safe collection to hold results
    ConcurrentBag<string> results { get; set; } = new ConcurrentBag<string>();
    List<string> urls { get; set; } = new List<string>() { "www.google.com", "www.facebook.com", "www.yahoo.com" };
    //List to hold URL watchers
    List<UrlWatcher> watchers { get; set; } = new List<UrlWatcher>(); 

    private void StartBtn_Click(object sender, EventArgs e)
    {
        //Create a separate watcher for each URL. Subscribe to the OnDataReceived event. Start the watchers.
        foreach(var url in urls)
        {
            UrlWatcher w = new UrlWatcher(url);
            w.OnDataReceived += (o, oe) => results.Add(oe.CollectedData);
            w.Start();
            watchers.Add(w);
        }
    }