如何等待任务';结果';属性具有实际结果

本文关键字:结果 属性 何等待 任务 等待 | 更新日期: 2023-09-27 18:24:21

我有一组任务,收到这些任务后,我使用

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

其中CompleteTasks()是我在所有任务都应该完成计算结果后使用的方法。这是第一次,但当我再次浏览它时,一些Tasks results属性显示"尚未计算",它仍然会浏览我的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();
    }

如何等待任务';结果';属性具有实际结果

我没有仔细梳理您的所有代码,但您似乎没有正确使用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:使用Task.WaitAll(tasks);这将等待所有剩余任务结束;

解决方案2:使用类似的东西:

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

希望能有所帮助。

我能够处理这个问题。在重新检查之前,我调用了Thread.Sleep方法,让系统有时间完成,这样可以顺利地得到所有结果。