Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/273.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#_.net_Multithreading_Asynchronous_Parallel Processing - Fatal编程技术网

C# 如何检查此间隔是否正在运行?

C# 如何检查此间隔是否正在运行?,c#,.net,multithreading,asynchronous,parallel-processing,C#,.net,Multithreading,Asynchronous,Parallel Processing,我已经设置了一组控制台.WriteLines,据我所知,当我在.NET Fiddle中运行以下命令时,它们都没有被调用 using System; using System.Net; using System.Linq.Expressions; using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Timers; using System.Collections.Generi

我已经设置了一组
控制台.WriteLine
s,据我所知,当我在.NET Fiddle中运行以下命令时,它们都没有被调用

using System;
using System.Net;
using System.Linq.Expressions;
using System.Linq;  
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using System.Collections.Generic;

public class Program
{
    private static readonly object locker = new object();
    private static readonly string pageFormat = "http://www.letsrun.com/forum/forum.php?board=1&page={0}";

    public static void Main()
    {
        var client = new WebClient();

        // Queue up the requests we are going to make
        var tasks = new Queue<Task<string>>(
            Enumerable
            .Repeat(0,50)
            .Select(i => new Task<string>(() => client.DownloadString(string.Format(pageFormat,i))))
        );

        // Create set of 5 tasks which will be the at most 5
        // requests we wait on
        var runningTasks = new HashSet<Task<string>>();
        for(int i = 0; i < 5; ++i)
        {
            runningTasks.Add(tasks.Dequeue());
        }

        var timer = new System.Timers.Timer
        {
            AutoReset = true,
            Interval = 2000 
        };

        // On each tick, go through the tasks that are supposed
        // to have started running and if they have completed
        // without error then store their result and run the
        // next queued task if there is one. When we run out of 
        // any more tasks to run or wait for, stop the ticks.
        timer.Elapsed += delegate
        {
            lock(locker)
            {
                foreach(var task in runningTasks)
                {
                    if(task.IsCompleted)
                    {
                        if(!task.IsFaulted)
                        {
                            Console.WriteLine("Got a document: {0}", 
                                task.Result.Substring(Math.Min(30, task.Result.Length)));

                            runningTasks.Remove(task);

                            if(tasks.Any())
                            {
                                runningTasks.Add(tasks.Dequeue());
                            }
                        }
                        else
                        {
                            Console.WriteLine("Uh-oh, task faulted, apparently");
                        }
                    }
                    else if(!task.Status.Equals(TaskStatus.Running)) // task not started
                    {
                        Console.WriteLine("About to start a task.");
                        task.Start();
                    }
                    else
                    {
                        Console.WriteLine("Apparently a task is running.");
                    }
                }   

                if(!runningTasks.Any())
                {
                    timer.Stop();
                }
            }

        };
    }
}
使用系统;
Net系统;
使用System.Linq.Expressions;
使用System.Linq;
使用系统线程;
使用System.Threading.Tasks;
使用系统计时器;
使用System.Collections.Generic;
公共课程
{
私有静态只读对象锁定器=新对象();
专用静态只读字符串pageFormat=”http://www.letsrun.com/forum/forum.php?board=1&page={0}";
公共静态void Main()
{
var client=new WebClient();
//将我们要提出的请求排队
var tasks=新队列(
可枚举
.重复(0,50)
.Select(i=>newtask(()=>client.DownloadString(string.Format(pageFormat,i)))
);
//创建一组5个任务,最多5个
//我们等待的请求
var runningTasks=new HashSet();
对于(int i=0;i<5;++i)
{
runningTasks.Add(tasks.Dequeue());
}
var timer=新的System.Timers.timer
{
自动重置=真,
间隔=2000
};
//在每个勾号上,完成假设的任务
//是否已开始运行,以及是否已完成
//然后无错误地存储结果并运行
//下一个排队的任务(如果有)。当我们用完
//要运行或等待的任何其他任务,请停止计时。
timer.appead+=委托
{
锁(储物柜)
{
foreach(runningTasks中的var任务)
{
如果(任务已完成)
{
如果(!task.IsFaulted)
{
WriteLine(“获取了一个文档:{0}”,
task.Result.Substring(Math.Min(30,task.Result.Length));
运行任务。删除(任务);
if(tasks.Any())
{
runningTasks.Add(tasks.Dequeue());
}
}
其他的
{
WriteLine(“哦,显然是任务出错”);
}
}
否则,如果(!task.Status.Equals(TaskStatus.Running))//任务未启动
{
WriteLine(“即将开始任务”);
task.Start();
}
其他的
{
WriteLine(“显然有任务正在运行”);
}
}   
如果(!runningTasks.Any())
{
timer.Stop();
}
}
};
}
}
我也希望得到关于如何简化或修复这方面任何错误逻辑的建议。我想做的模式是

(1) 创建一个包含N个任务的队列

(2) 创建一组M个任务,第一个M个从(1)中退出队列的项目

(3) 启动正在运行的M任务

(4) X秒后,检查是否已完成任务

(5) 对于任何已完成的任务,对结果执行一些操作,从集合中删除该任务,并将其替换为队列中的另一个任务(如果队列U中还有任何任务)

(6) 无限期地重复(4)-(5)

(7) 如果集合中没有剩余任务,我们就完成了


但是也许有更好的方法来实现它,或者可能有一些.NET函数可以轻松地封装我正在尝试做的事情(web请求以指定的最大并行度并行)。

代码中有几个问题,但是,由于您正在寻找更好的实现方法,您可以使用
Parallel.for
Parallel.ForEach

Parallel.For(0, 50, new ParallelOptions() { MaxDegreeOfParallelism = 5 }, (i) =>
{
     // surround with try-catch
     string result;
     using (var client = new WebClient()) {
          result = client.DownloadString(string.Format(pageFormat, i));
     }
     // do something with result
     Console.WriteLine("Got a document: {0}", result.Substring(Math.Min(30, result.Length)));
});
它将并行执行主体(在任何给定时间不超过5个任务)。当一项任务完成时——下一项任务开始,直到它们全部完成,就像你想要的那样

更新。使用这种方法有几个等待来限制任务,但最直接的是睡眠:

Parallel.For(0, 50, new ParallelOptions() { MaxDegreeOfParallelism = 5 },  
(i) =>
{
    // surround with try-catch
    var watch = Stopwatch.StartNew();
    string result;
    using (var client = new WebClient()) {
         result = client.DownloadString(string.Format(pageFormat, i));
    }
    // do something with result
    Console.WriteLine("Got a document: {0}", result.Substring(Math.Min(30, result.Length)));
    watch.Stop();
    var sleep = 2000 - watch.ElapsedMilliseconds;
    if (sleep > 0)
          Thread.Sleep((int)sleep);
});

这不是对你问题的直接回答。我只是想提出另一种方法

我建议您考虑使用Microsoft的反应式框架(NuGet“System.Reactive”)来完成这类工作

然后,您可以这样做:

var query =
    Observable
        .Range(0, 50)
        .Select(i => string.Format(pageFormat, i))
        .Select(u => Observable.Using(
            () => new WebClient(),
            wc => Observable.Start(() => new { url = u, content = wc.DownloadString(u) })))
        .Merge(5);

IDisposable subscription = query.Subscribe(x =>
{
    Console.WriteLine(x.url);
    Console.WriteLine(x.content);
});

它是异步的,可以通过调用
subscription.Dispose()
随时停止进程

您选择这种方法而不只是将任务推送到线程池中有什么原因吗?我不是说你错了,我只是好奇。一个带有特定DOP的简单ActionBlock可以解决这个问题。我不想这么做的一个原因是,它有可能让网站充斥着大量的请求。如果我很快得到前5个响应,我仍然希望在发出下一批请求之前等待一两秒钟。您知道站点是如何限制并发请求的吗?我的意思是,像“Y秒内不超过X个请求”之类的东西。不,我没有。但是让我们假设我这样做了:那么对于X和Y来说,这个过程是什么呢?你真的不应该做
new-WebClient()。DownloadString(
as
WebClient
IDisposable
@Enigmativity),而一般来说,WebClient的Dispose没有任何用处(它是IDisposable的,因为它继承自IComponent),因此不处理它不会有什么坏处(不会留下任何打开的流、挂起的web请求或类似的内容)。在这种情况下添加如何限制请求不会有什么坏处(例如,作者需要在每批5个请求之间至少间隔两秒)@Evk Rx使用Rx进行节流要容易得多,它已经有操作员来节流或缓冲events@PanagiotisKanavos是的,但是