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

C# 任务处于等待或运行状态的时间异常长

C# 任务处于等待或运行状态的时间异常长,c#,concurrency,task,C#,Concurrency,Task,我有一个程序,可以处理并行运行的各种任务。单个任务充当排序管理器,确保在运行下一个任务之前满足某些条件。然而,我发现有时任务会在等待或运行状态下等待很长时间。以下是代码: mIsDisposed = false; mTasks = new BlockingCollection<TaskWrapper>(new ConcurrentQueue<TaskWrapper>()); Task.Factory.StartNew(() => { while

我有一个程序,可以处理并行运行的各种任务。单个任务充当排序管理器,确保在运行下一个任务之前满足某些条件。然而,我发现有时任务会在等待或运行状态下等待很长时间。以下是代码:

mIsDisposed = false;
mTasks      = new BlockingCollection<TaskWrapper>(new ConcurrentQueue<TaskWrapper>());

Task.Factory.StartNew(() => {
    while (!mIsDisposed) {
         var tTask = mTasks.Take();
         tTask.task.Start();
         while (tTask.task.Status == TaskStatus.WaitingToRun) {
             Console.WriteLine("Waiting to run... {0}", tTask.task.Id);
             Thread.Sleep(200);
         }
         tTask.ready.Wait();
     }
     mTasks.Dispose();
});

DoWork();
DoWork();
DoWork();
DoWork();
DoWorkAsync();
DoWorkAsync();
DoWorkAsync();
DoWorkAsync();
DoWorkAsync();
DoWork();
和任务当前仅在两个位置添加:

public void DoWork()
{
    DoWorkAsync().Wait();
}

public Task DoWorkAsync()
{
    ManualResetEvent next = new ManualResetEvent(false);

    Task task  = new Task(() => ActualWork(next));
    Task ready = Task.Factory.StartNew(() => next.Wait());

    mTasks.Add(new TaskWrapper() {
        task  = task,
        ready = ready
    });
    return task;
}
其中
ActualWork(next)
调用
next.Set()

这将对工作进行排队并等待,直到设置了
next
,然后才允许继续下一个工作项。您可以通过调用
DoWork()
等待整个任务完成后再继续,也可以一次对多个任务排队(这些任务应该在设置了
next
之后运行)

但是,当通过
doworksync()
添加任务时,在调用
tTask.task.Start()
后,
tTask.task
处于WaitingToRun状态一段时间(如30秒到一分钟),然后神奇地开始运行。我已经使用while循环监视了这个,并且
正在等待运行#将显示一段时间

调用
DoWork()
总是立即运行。我确信这与对设置为运行的任务调用
Wait
有关

在这里,我不知所措

更新:

我已经设法使代码正常工作,但我仍然想知道为什么首先会出现问题

经过一些实验性的改变后,我成功地解决了自己的问题,但这更像是一个“哦,所以我做不到”而不是一个好的解决方案。原来我的问题是让任务排队运行得太快。通过修改
doworksync()
以不再使用
Task.Factory.StartNew
并将
tTask.ready.Wait()
更改为
tTask.ready.RunSynchronously
我已经设法解决了我的问题


TaskScheduler
延迟我的任务调度有什么原因吗?我是否占用了一些基础资源?这里发生了什么?

线程将在系统的线程池中运行。线程池始终具有最小可用线程数(请参阅)。如果您尝试创建的线程数量超过该数量,则在每个新线程启动之间将引入大约500毫秒的延迟

线程池中还有一个最大线程数(请参阅),如果达到该限制,将不会创建新线程;在调度新线程之前,它将一直等到旧线程死亡(或者更确切地说,重新调度旧线程以运行新线程)


不过,你不太可能达到这个极限——它可能超过1000英镑。

刚刚遇到了类似的问题

我有一堆类似的任务在fite循环中运行,其中一个任务经常处于WaitingToRun状态

以这种方式创建任务为我带来了好处:

_task = new Task(() => DoSmth(_cancellationTokenSource.Token), TaskCreationOptions.LongRunning);
_task.Start();

好的,我刚刚遇到了一个类似的问题。一些创建并启动任务的代码已经运行,但任务从未启动(它只是将状态更改为WaitingToRun)

在这个线程中尝试了其他选项但没有效果后,我仔细考虑了一下,并意识到调用此方法的代码本身是在一个延续任务中调用的,该任务已指定在UI任务调度器上运行(因为它需要更新UI)

大概是

void Main()
{
    var t1 = new Task(() => Console.WriteLine("hello, I'm task t1"));
    t1.ContinueWith(t => CreateAndRunASubTask(), TaskScheduler.FromCurrentSynchronizationContext());
    t1.Start();

    Console.WriteLine("All tasks done with");
}

// Define other methods and classes here
public void CreateAndRunASubTask()
{
    var tsk = new Task(() => Console.WriteLine("hello, I'm the sub-task"));
    tsk.Start();
    Console.WriteLine("sub-task has been told to start");
    tsk.Wait();
    // the code blocks on tsk.Wait() indefinately, the tsk status being "WaitingToRun"
    Console.WriteLine("sub-task has finished");
}
修复非常简单-在指定延续任务时,需要指定TaskContinuationOption:TaskContinuationOptions.HidesScheduler

这有。。。(摘自XML注释)

指定由continuation通过调用方法创建的任务 例如System.Threading.Tasks.Task.Run(System.Action)或 System.Threading.Tasks.Task.ContinueWith(System.Action{System.Threading.Tasks.Task}) 查看默认的调度程序(System.Threading.Tasks.TaskScheduler.default),而不是
而不是作为当前计划程序运行此延续的计划程序

ie(在我的例子中)


希望这有助于别人,因为它让我难堪了好一阵子

就这样!奇怪的是,它们延迟了新线程的启动。我认为这是为了使您的程序不会无意中试图扼杀系统上的其他进程。。。但是伊恩诺。
void Main()
{
    var t1 = new Task(() => Console.WriteLine("hello, I'm task t1"));
    t1.ContinueWith(t => CreateAndRunASubTask(), TaskScheduler.FromCurrentSynchronizationContext());
    t1.Start();

    Console.WriteLine("All tasks done with");
}

// Define other methods and classes here
public void CreateAndRunASubTask()
{
    var tsk = new Task(() => Console.WriteLine("hello, I'm the sub-task"));
    tsk.Start();
    Console.WriteLine("sub-task has been told to start");
    tsk.Wait();
    // the code blocks on tsk.Wait() indefinately, the tsk status being "WaitingToRun"
    Console.WriteLine("sub-task has finished");
}
t1.ContinueWith(t => 
    CreateAndRunASubTask(), 
    System.Threading.CancellationToken.None, 
    TaskContinuationOptions.HideScheduler,
    TaskScheduler.FromCurrentSynchronizationContext());