如何等到任务'Result'属性有实际结果

时间:2013-07-23 14:57:57

标签: c# parallel-processing task-parallel-library task

在我收到使用

的任务后,我有一系列任务
Task.Factory.ContinueWhenAll(TasksList.ToArray(), CompleteTasks);

其中CompleteTasks()是我在所有任务完成后计算结果的方法。这是第一次使用,但是当我再次浏览它时,一些任务结果属性显示“尚未计算”'它仍然通过我的CompleteTasks方法。处理这个问题的最佳方法是什么?

以下是完整的代码:

public Checker(IEnumerable<Website> websites)
    {
        WebsiteHelper.Websites = websites.ToList<Website>();
        Check(WebsiteHelper.Websites);

    }

public void Check(IList<Website> tempWeb)
    {
        int mySiteCounter = 0;
        // Go through each website in the list in parallel
        Parallel.ForEach(tempWeb, web =>
        {
            TempWebResult.Add(new WebsiteResult { });
            try
            {

                StartingTime = DateTime.Now;
                PageCheck(web, mySiteCounter++);
                EndingTime = DateTime.Now;

            }
            //write the Message to a log
            //Catch Exceptions

             });

        CheckNewResult();
    }

public void PageCheck(Website webParam, int mySiteCounter)
    {
        TempCounter = mySiteCounter;
        TempURL = webParam.SiteUrl;
        Uri uri = new Uri(TempURL);
        HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(uri);
        myReq.Method = WebRequestMethods.Http.Get; // Used to contact the Internet resource


        try
        {

            myReq.KeepAlive = false;
            myReq.Timeout = 5 * 60 * 1000; //set to 10 minutes

            var checkResult = TempWebResult.ElementAt(mySiteCounter);


            //Use .FromAsync to start asynchronous operation request and to return the actual web response
            try
            {
                checkResult.RequestSentTime = DateTime.Now;
                Stopwatch WatchTimer = Stopwatch.StartNew();
                Task<WebResponse> task = Task<WebResponse>.Factory.FromAsync(
                    myReq.BeginGetResponse,
                    myReq.EndGetResponse,
                    null);

                //Add a task to the task list
                TempTasksList.Add(task);



                Console.WriteLine(mySiteCounter + ": Url to check: " + myReq.RequestUri);

                //Continue after request and response have been made
                task.ContinueWith(t =>
                    {


                        var responseCode = (HttpWebResponse)t.Result;
                        WatchTimer.Stop();
                        checkResult.milli = WatchTimer.ElapsedMilliseconds;
                        checkResult.ResponseReceivedTime = DateTime.Now;
                        //diff = checkResult.ResponseReceivedTime - checkResult.RequestSentTime;
                        //checkResult.milli = (int)diff.TotalMilliseconds;

                        checkResult.Url = webParam.SiteUrl;
                        checkResult.SystemStatus = "Up";
                        webParam.SiteStatus = checkResult.SystemStatus;
                        checkResult.SystemId = mySiteCounter + "-" + myReq.RequestUri.ToString();


                        Console.WriteLine(mySiteCounter + "Url that came back: " + responseCode.ResponseUri);

                        ReadStreamFromResponse(t.Result);

                        if (responseCode.StatusCode == HttpStatusCode.OK) // Checks if status is OK or not
                        {

                            checkResult.ResponseStatus = responseCode.StatusCode.ToString();
                            checkResult.ResponseStatusCode = "Up";
                            checkResult.SystemStatus = "Up";
                            webParam.SiteStatus = checkResult.SystemStatus;
                            checkResult.StatusFlag = true;
                            //Return the Response Url
                            checkResult.ResponseUrl = responseCode.ResponseUri.ToString();
                        }


                        if (checkResult.SystemName == null)
                            checkResult.SystemName = "";
                        if (checkResult.Message == null)
                            checkResult.Message = "";
                        if (checkResult.ResponseUrl == null)
                            checkResult.ResponseUrl = "";


                    });
                task.ContinueWith((t) =>
                    {
                        WatchTimer.Stop();
                        checkResult.milli = WatchTimer.ElapsedMilliseconds;
                        ErrorMessage = GetException(t.Exception);
                        checkResult.ResponseReceivedTime = DateTime.Now;
                       // diff = checkResult.ResponseReceivedTime - checkResult.RequestSentTime;
                       // checkResult.milli = (int)diff.TotalMilliseconds;
                        Console.WriteLine("Status Not Ok");
                        checkResult.SystemId = mySiteCounter + "-" + myReq.RequestUri.ToString();
                        checkResult.ResponseStatus = ErrorMessage;
                        checkResult.ResponseStatusCode = "Down";
                        checkResult.SystemStatus = "Down";
                        webParam.SiteStatus = checkResult.SystemStatus;
                        checkResult.StatusFlag = false;
                    },
                    TaskContinuationOptions.OnlyOnFaulted);

            }
             //Exceptions caught

                       }
        //Exceptions caught
    }


/// <summary>
    /// This method converts the TasksList into an array
    /// and calls the Complete Tasks method
    /// </summary>
    private void CheckNewResult()
    {

        Task.Factory.ContinueWhenAll(TempTasksList.ToArray(), CompleteTasks);

    }

    /// <summary>
    /// This method waits until all tasks have ran to
    /// completion so it can print results
    /// </summary>
    /// <param name="tasks"> Array of completed tasks</param>
    private void CompleteTasks(Task[] tasks)
    {

        WebsiteHelper.myLog.Info("***********************************************************");
        WebsiteHelper.myLog.Info("ready to print check results now");

        //Wait until all tasks have ran to completion

        if (tasks.Any(t => t.Status == (TaskStatus.RanToCompletion) || t.Status == (TaskStatus.Faulted)))
        {


            Parallel.ForEach(TempWebResult, result =>
            {
                //Console.WriteLine(result);
                // Console.WriteLine("new line");

                WebsiteHelper.myLog.Info(result.SQL);

            });
        }

        if(DownSitesHandler.FirstTime == true)
        {
            DownSitesHandler.FirstTime = false;
            CheckDownSites();
            if (WebsiteHelper.Self().HasDownSite == true)
                ReCheck();


        }

        Console.WriteLine("done printing all results");
    }

/// <summary>
    /// This method rechecks all down websites
    /// </summary>
    public void ReCheck()
    {

        //Checker newCheckerObject = new Checker(downsites);
        WebsiteHelper.myLog.Info(DateTime.Now + " -- Begin to re-check down sites ");
        IList<Website> temporaryWebList = DownSitesHandler.downsites.ToList<Website>();
        Check(temporaryWebList);
        //newCheckerObject.SendRequest();
    }

3 个答案:

答案 0 :(得分:2)

我没有梳理所有代码,但似乎你没有正确使用continuation。延续本身就是一项单独的任务,在某些时候,你需要等待它完成。例如:

var first = Task.Run(() => { Console.Write("First"); });
var second = first.ContinueWith(t => Console.WriteLine("Second"));
second.Wait();

如果您只等“第一个”,则无法保证延续已完成。 ContinueWhenAll方法也是如此,它返回您需要等待的任务。

此外,向同一任务添加多个延续并不意味着两者之间存在任何优先级关系。在先行任务完成后,它们可以以任何顺序启动,并行运行,无论如何。例如:

var taskA = Task.Run(() => { Console.Write("A"); });
var taskB1 = taskA.ContinueWith(t => Console.WriteLine("B1"));
var taskB2 = taskA.ContinueWith(t => Console.WriteLine("B2"));
var bothFinished = Task.WhenAll(taskB1, taskB2);
bothFinished.Wait();

在这里,您可能会看到以任何顺序打印B1和B2,如果您想确保它们已经运行,您需要等待两者完成。

这可能是也可能不是你所有问题的解决方案,但它应该是开始的。

答案 1 :(得分:2)

发生的事情是你的任务还没有完成他们的工作。

解决方案1:使用Task.WaitAll(tasks);这将等待所有剩余的任务结束;

解决方案2:使用以下内容:

            var continuation = Task.Factory.ContinueWhenAll(
                        tasks,
                        (antecedents) =>
                        {
                            //Do Some Work Here
                        });
            continuation.Wait();

希望有所帮助。

答案 2 :(得分:-4)

我能够处理这个问题。在重新检查之前,我调用了Thread.Sleep方法来给系统完成时间,这使得所有结果都能顺利进行。

相关问题