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

C# 为什么我的任务没有取消?

C# 为什么我的任务没有取消?,c#,task,libcurl,C#,Task,Libcurl,我正在运行一个周期性地卷曲到URL列表的过程,以测试这些网站的性能。我的主程序基本上是一个do…sleep…while循环,它调用一个函数,每N秒运行一次测试,并通过键盘中断将其关闭。简而言之,我的代码如下: public void runTest() { if(isRunning) { return; //Plus some logging that one or more of the tests hasn't completed } try {

我正在运行一个周期性地卷曲到URL列表的过程,以测试这些网站的性能。我的主程序基本上是一个do…sleep…while循环,它调用一个函数,每N秒运行一次测试,并通过键盘中断将其关闭。简而言之,我的代码如下:

public void runTest()
{
   if(isRunning)
   {
      return; //Plus some logging that one or more of the tests hasn't completed
   }
   try {
       isRunning = true;
       Curl.GlobalInit((int)CURLinitFlag.CURL_GLOBAL_ALL);
       CancellationTokenSource cts = new CancellationTokenSource(httpTimeoutValueMs * 2);
       foreach (var url in urls)
            taskList.Add(doAsyncCurls(url, cts))
       List<CurlResults> listOfResults = Task.WhenAll(taskList.Select(x => x)).Result.ToList();
       taskList.Clear();
  }
  catch {/*Some exception handling code*/}
  finally { 
    isRunning = false; 
    Curl.GlobalCleanup();
  }
}
private static async Task<CurlResults> doAsyncCurls(string url, CancellationTokenSource cts)
{
    try
    {
      /*Initiate a Curl using libCurl*/
      Easy easy = new Easy();
      easy.SetOpt(CURLoption.CURLOPT_URL, url);
      easy.SetOpt(CURLoption.CURLOPT_DNS_CACHE_TIMEOUT, 0); //Disables DNS cache
      easy.SetOpt(CURLoption.CURLOPT_CONNECTTIMEOUT, httpTimeoutValueMs / 1000); //20sec timeout

      Task t = new Task(() => easy.Perform(), cts.Token);
      t.Start();
      await t;
      return new CurlResults(/*valid results parameters*/);
    } 
    catch (TaskCanceledException)
    { /*Cancellation token invoked*/
        return new CurlResults(/*Invalid results parameters*/);
    }
    catch (Exception e)
    { /*Other exception handling*/ 
        return new CurlResults(/*Invalid results parameters*/);
    }
doAsyncCurl函数执行它在tin上所说的操作,将http超时值设置为取消令牌的一半,这样http请求应该在调用取消令牌之前消失,并生成一个负面结果。我添加了取消令牌以尝试处理我的问题,如下所示

我让它运行了很长一段时间——首先,一切都很好,但最终数百次,如果不是更多的迭代,通过定期运行测试调用,似乎其中一个任务被卡住了,取消令牌没有被调用,而curl测试过程实际上被卡住了


除了找出哪些URL是有问题的,而且它们都是有效的,还能做些什么来诊断出哪里出了问题?或者我的平行卷发一开始就完全错了?我很感激我可以实例化上一轮已经完成的URL的新卷发,并让挂起的一个挂起,而不是等待它们全部完成后再开始新的一批,但我不担心效率的提高。

取消没有自动性。您必须检查取消状态并结束执行或调用CancellationToken.ThrowIfCancellationRequested执行取消。CancellationToken将告诉您是否请求取消;取消必须由您自己完成

以下是您的问题:

Task t = new Task(() => easy.Perform(), cts.Token);
您正在将令牌传递给任务构造函数。如果在任务开始之前取消,这将对您有所帮助。一旦任务启动,执行的方法负责取消。简单。Perform不知道您的取消令牌,因此永远无法确定是否请求取消。因此,它将走到尽头


在任务执行过程中,您需要定期检查取消令牌,以实现所需目标。

传递对令牌的引用并不意味着任务主体中会自动取消任务。您仍然需要定期检查它。好的-我已经总结了我的取消令牌实现,但是我也不明白为什么Curl没有超时,我应该/可以在这一行之后使用t.waittimoutMs,而不是使用令牌和wait t t?是的,你可以,但这不会结束你的任务。它将继续运行到最后。@JetSetJim如果您这样做,那么代码就不会是异步的。您可以构建一个新任务,该任务将。您可以使用类似这样的方法创建一个任务,该任务将在取消令牌时完成,但这不会阻止操作继续执行…它想做的任何事情,如果这对您来说足够的话。@Sefe-那么这是否意味着挂起任务中实例化的easy.Perform将继续存在,直到完成为止?如果它在后续调用中一直挂起,则可能是一个问题,因为没有任何东西会对其进行整理。如果它引发异常,则会导致任务出错,从而结束任务。如果您想跟踪挂起的执行,您必须自己跟踪这些执行并采取相应的行动。任务框架本身不提供终止任务的方法。您可以找出某个任务正在运行的线程并终止该线程,但这是一个肮脏的解决方案,不推荐这样做。