0

我是使用回调和异步函数的新手,所以我有点不确定解决这个问题的最佳方法。

我创建了一个SendPhoto()由我的 GUI 调用的函数。该SendPhoto()函数与我的 GUI 位于一个单独的类中。

    public string SendPhoto(string filename)
    {
        byte[] response = PostFile(_url, filename);

        String responsestring = Encoding.ASCII.GetString(response);

        if (responsestring.StartsWith("ERROR:"))
            return responsestring;
        else if (responsestring.Contains("<valid>1</valid>"))
            return "OK";
        else
            return responsestring;
    }

我的PostFile()函数曾经调用WebClient.UploadFile(),响应返回到SendPhoto(),效果很好。然后我决定要异步发送照片,所以在我的PostFile()函数中,我将调用从 更改Uploadfile()UploadFileAsync()

但是,我意识到它UploadFileAsync()不会返回值,并且我必须使用 UploadFileCompletedEventHandler 来在完成上传后获取响应。所以,我在同一个类中编写了一个回调函数SendPhoto()PostFile()检索响应,在该函数上实例化一个 UploadFileCompletedEventHandler,并将它传递给我的PostFile()函数。

问题是我不确定如何将响应返回给SendPhoto()函数,以便它可以解释响应并将友好的响应发送回 GUI。以前,当一切都是同步的时,响应只是传回堆栈,但现在,响应又被删除了几层。

将响应从回调函数返回到 的最佳方法是什么SendPhoto(),现在PostFile()不能再将它返回给我?我想将事件处理程序回调移动到 GUI 并传递UploadFileCompletedEventHandlerto SendPhoto(),然后将其发送到PostFile(). 但我试图将“业务逻辑”(即解释响应)排除在 GUI 类之外。

4

1 回答 1

1

好的,今天早上又做了一些工作,并通过使用“await”找到了一个非常优雅的解决方案(感谢 Muctadir Dinar!)。我必须更改对 UploadFileTaskAsync() 的调用,以便它支持“await”关键字,并且我必须用“async”装饰我的所有方法并让它们返回任务,一直返回到 GUI 的按钮单击事件处理程序,但是当我完成后,它工作得很好!我相信这仅适用于 .NET 框架 4.5。

    private async void UploadPhotoButton_Click(object sender, EventArgs e)
    {
        ...
        string theResult = await MyProvider.SendPhotoAsync(pathToFile, new UploadProgressChangedEventHandler(UploadProgressCallback));
        OutputBox.Text = theResult;
    }

    public async Task<string> SendPhotoAsync(string filename, UploadProgressChangedEventHandler changedHandler)
    {
        byte[] response = await PostFileAsync(_url, filename, changedHandler);

        String responsestring = Encoding.ASCII.GetString(response);

        if (responsestring.StartsWith("ERROR:"))
            return responsestring;
        else if (responsestring.Contains("<valid>1</valid>"))
            return "OK";
        else
            return responsestring;
    }

    async Task<byte[]> PostFileAsync(string uri, string filename, UploadProgressChangedEventHandler changedHandler)
    {
        byte[] response = null;
        using (WebClient client = new WebClient())
        {
            client.Headers = GetAuthenticationHeader();
            client.UploadProgressChanged += changedHandler;

            response = await client.UploadFileTaskAsync(new Uri(uri), filename);
        }

        return response;
    }
于 2013-09-26T15:56:54.680 回答