我是否需要重写我的异步方法/类来实现我想要的功能?

时间:2010-11-19 22:04:31

标签: c# .net asynchronous windows-phone-7 iterator

我有一个类,它以异步和递归方式处理n个http请求/ repsonses。我很满意我的班级,直到我意识到我可能把自己编成了一个洞。基本上我想在读取每个响应之后提出一个事件,以确认应用程序是否已进入下一个或因任何原因提前完成。我承认我是异步编程的新手,所以我使用Async Enumerator类来帮助我。我不介意只要基本功能保持不变就重写这个方法或整个类,即需要n个请求并按顺序读取它们。

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Webtext.Implementations;
using Webtext.Interfaces;
using Wintellect.Threading.AsyncProgModel;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace Webtext.Implementations
{
public class SMSSender : Interfaces.IOperator
{
    private HttpWebRequest httpRequester;
    private HttpWebResponse httpResponse;
    private IOperatorRequestCollection requestCollection;
    private IUrlBuilder urlBuilder;
    private AsyncEnumerator asyncEnum;
    private CookieContainer cookieContainer;
    CookieCollection cookieCollection;

    public SMSSender()
    {
        cookieContainer = new CookieContainer();
        cookieCollection = new CookieCollection();
    }

    public void Send(string UserName, string Password, string MessageRecipient, string Message, OperatorList Operator)
    {
        urlBuilder = new UrlBuilder();

        requestCollection = new OperatorRequestCollection { OperatorRequestList = urlBuilder.GetUrlRequests(UserName, Password, MessageRecipient, Message, Operator) };

        ProcessRequests();
    }

    private void ProcessRequests()
    {
        asyncEnum = new AsyncEnumerator();
        asyncEnum.BeginExecute(GetData(asyncEnum, requestCollection.GetCurrentRequest()), asyncEnum.EndExecute);
    }

    private IEnumerator<Int32> GetData(AsyncEnumerator asyncEnum, IOperatorRequest request)
    {
        httpRequester = (HttpWebRequest)WebRequest.Create(request.RequestUrl);
        httpRequester.AllowAutoRedirect = true;
        httpRequester.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.6) Gecko/20060728 Firefox/1.5.0.6";

        if (httpRequester.CookieContainer == null)
            httpRequester.CookieContainer = cookieContainer;

        httpRequester.BeginGetResponse(asyncEnum.End(), null);
        yield return 1;

        httpResponse = (HttpWebResponse)httpRequester.EndGetResponse(asyncEnum.DequeueAsyncResult());

        if (httpResponse.StatusCode == HttpStatusCode.OK)
        {
            // Create the stream, encoder and reader.
            Stream responseStream = httpResponse.GetResponseStream();
            Encoding streamEncoder = Encoding.UTF8;
            StreamReader responseReader = new StreamReader(responseStream, streamEncoder);
            CheckRequest(request, responseReader.ReadToEnd());
        }
    }

    private void CheckRequest(IOperatorRequest Request, string Response)
    {
        if (Response.Contains(Request.SuccessMessage))
        {
            AddCookiesToRequest();

            bool lastCallFinished = false;
            if (requestCollection.GetCurrentRequest() != requestCollection.GetLastRequest())
            {
                requestCollection.MoveNextToCurrent();
                ProcessRequests();
            }
            else
            {
                if (lastCallFinished == false)
                {
                    ProcessRequests();
                    lastCallFinished = true;
                }
            }
        }
    }

    private void AddCookiesToRequest()
    {
        // This method is O2 specific at the moment. I do not know if this sort of methods
        // will be needed for the others so for the moment it stays as is.
        cookieCollection.Add(httpResponse.Cookies);
        foreach (Cookie cookie in cookieCollection)
        {
            cookie.Path = "/";
            cookie.Domain = "o2online.ie";
        }
        cookieContainer.Add(httpResponse.ResponseUri, cookieCollection);
    }
}

}

编辑:此编辑是为了解释我要做的事情:

我基本上使用HttpWebRequest发出5(这可能是n个)请求。我正在递归地执行此操作,因为每个新请求都取决于从先前请求获得的响应。此功能目前有效。

我遇到的问题是,由于响应是异步回来的,我无法回到UI线程让UI知道我有多远。如果任何响应失败,请求集合将作为一个整体失败,因此最好知道哪个请求失败以及原因。

我还想让另一个异步操作工作,可以接收这些数据并使用不确定的进度条显示它。这样,用户就可以从UI获取关于操作的距离以及是否失败的实时数据。我在这里尝试了一个背景工作者但是因为第一个请求是异步的而且DO_WORK是一个同步方法,所以在工作实际完成之前调用了一个backround worker的WORK_Completed事件。

AsyncEnumerator。它本质上使用枚举器来指定yield之后要做什么(当HttpEndGetResponse准备就绪时,它调用next。这提升了一些问题,因为我可以将事件编组回UI线程与进度工作者交谈,但它仍然很混乱,所以我还没有实现它。

我想要做的是在SENDER对象上触发SEND方法,然后使用PROGRESSDISPLAY对象在不同的​​异步调用上触发SHOW_PROGRESS方法。因为Send方法的每次迭代都会将发送数据发送回UI,后者将其从PROGRESSDISPLAY对象发送出去并允许它更新,直到最终调用将告诉PROGRESSDISPLAY关闭。

1 个答案:

答案 0 :(得分:0)

最后,重写似乎是最好的选择。新类具有将被触发回UI线程的方法。并不是说这堂课错了。事实上它工作正常。问题在于我从未允许任何回应机制。一旦完成,我将用新课程更新这篇文章。