我有一些代码如下所示:

Class1

Task<List<ConfSession>> getSessionsTask = Task.Factory.StartNew(() =>
            {
                var confSessions =
                    TaskHelper<ConfSession>.InvokeTaskMagic(request);
                //PROBLEM - THIS CODE RACES TO THE NEXT LINE
                //BEFORE confSessions IS POPULATED FROM THE LINE ABOVE - IE
                //confSessions IS ALWAYS AN EMPTY LIST
                //WHEN IT'S RETURNED
                return confSessions;
            }
        );

Class2 (TaskHelper)
//methods
public static List<T> InvokeTaskMagic(HttpWebRequest request)
{
    var resultList = new List<T>();

    Task<WebResponse> task1 = Task<WebResponse>.Factory.FromAsync(
        (callback, o) => ((HttpWebRequest)o).BeginGetResponse(callback, o)
        , result => ((HttpWebRequest)result.AsyncState).EndGetResponse(result)
        , request);

    task1.ContinueWith((antecedent) =>
    {
        if (antecedent.IsFaulted)
        {
            return;
        }

        WebResponse webResponse;
        try
        {
            webResponse = task1.Result;
        }
        catch (AggregateException ex1)
        {
            throw ex1.InnerException;
        }

        string responseString;

        using (var response = (HttpWebResponse)webResponse)
        {
            using (Stream streamResponse = response.GetResponseStream())
            {
                StreamReader reader = new StreamReader(streamResponse);
                responseString = reader.ReadToEnd();
                reader.Close();
            }
        }

        if (responseString != null)
        {
            resultList =
               JsonConvert.DeserializeObject<List<T>>(responseString);
        }
    });

    return resultList;
}

TaskHelper 是我创建的一个类,用于标准化我在几种方法中拥有的一堆冗余任务代码。它的存在只是为了获取 HttpWebRequest,在 Task 中执行它,在 ContinueWith 块中获取响应,将响应解析为 List<T> ,并返回 List<T>

我将 Class1 对 TaskHelper 的调用封装在一个任务中,因为我需要在继续 class1 之前从 InvokeTaskMagic 方法中获取结果(即 class1 中的下一步是使用 List<T> 。正如代码中的注释中所说,我的问题是因为 class1 中的 Task 每次都返回一个空列表,因为它没有等待 TaskHelper 类中的 InvokeTaskMagic 方法的响应。

这是预期的吗?有没有办法让 getSessionsTask 等待返回直到 TaskHelper.InvokeTaskMagic 返回?

更新:
工作代码如下 - 感谢 Servy 的帮助。
public static class TaskHelper<T> where T : class
{
    //methods
    public static Task<List<T>> InvokeTaskMagic(HttpWebRequest request)
    {
        var resultList = new List<T>();

        Task<WebResponse> task1 = Task<WebResponse>.Factory.FromAsync(
            (callback, o) => ((HttpWebRequest)o).BeginGetResponse(callback, o)
            , result => ((HttpWebRequest)result.AsyncState).EndGetResponse(result)
            , request);

        return task1.ContinueWith<List<T>>((antecedent) =>
        {
            if (antecedent.IsFaulted)
            {
                return new List<T>();
            }

            WebResponse webResponse;
            try
            {
                webResponse = task1.Result;
            }
            catch (AggregateException ex1)
            {
                throw ex1.InnerException;
            }

            string responseString;

            using (var response = (HttpWebResponse)webResponse)
            {
                using (Stream streamResponse = response.GetResponseStream())
                {
                    StreamReader reader = new StreamReader(streamResponse);
                    responseString = reader.ReadToEnd();
                    reader.Close();
                }
            }

            if (responseString != null)
            {
                return JsonConvert.DeserializeObject<List<T>>(responseString);
            }
            else
            {
                return new List<T>();
            }
        });
    }
}

InvokeTaskMagic 方法的调用方式如下:
var getCommentsAboutTask = Task.Factory.StartNew(() =>
            {
                var comments = TaskHelper<Comment>.InvokeTaskMagic(request);
                return comments;
            });

        getCommentsAboutTask.ContinueWith((antecedent) =>
            {
                if (antecedent.IsFaulted)
                { return; }

                var commentList = antecedent.Result.Result;
                UIThread.Invoke(() =>
                {
                    foreach (Comment c in commentList)
                    {
                        AllComments.Add(c);
                        GetCommentRelatedInfo(c);
                    }
                });
            });

最佳答案



当然,只需在第二个任务的延续而不是第一个任务上调用 ContinueWith

如果您需要等待两者都完成,您可以使用 Task.Factory.ContinueWhenAll

关于c# - 来自 2 级 Task.ContinueWith 的意外行为,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13955631/

10-11 15:42