简体   繁体   中英

Best way to get callback value back to the function that initiated async method?

I'm new at using callbacks and async functions, so I'm a bit unsure of the best way to approach this.

I created a function called SendPhoto() that is called by my GUI. The SendPhoto() function is in a separate class from my 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;
    }

My PostFile() function used to call WebClient.UploadFile() , and the response was returned to SendPhoto() , and it worked great. Then I decided I wanted to send the photo asynchronously, so in my PostFile() function, I changed the call from Uploadfile() to UploadFileAsync() .

However, I realized that UploadFileAsync() doesn't return a value, and I have to use a UploadFileCompletedEventHandler to get the response when it's done uploading. So, I wrote a callback function in the same class as SendPhoto() and PostFile() to retrieve the response, instantiated a UploadFileCompletedEventHandler on that function, and passed it into my PostFile() function.

The problem is that I'm not sure how the get the response back to the SendPhoto() function, so that it can interpret the response and send the friendly response back to the GUI. Before, when everything was synchronous, the response was just passed back up the stack, but now, the response is coming back a couple layers removed.

What is the best way to get the response back from the callback function to SendPhoto() , now that PostFile() can no longer return it to me? I thought of moving the event handler callback to the GUI and passing the UploadFileCompletedEventHandler to SendPhoto() , which would in turn send it to PostFile() . But I am trying to keep "business logic" (ie interpreting the response) out of the GUI class.

Ok, worked on it some more this morning, and found a very elegant solution by using "await" (thanks, Muctadir Dinar!). I had to change my call to UploadFileTaskAsync(), in order for it to support the "await" keyword, and I had to decorate all of my methods with "async" and make them return task, all the way back to the GUI's button click event handler, but when I was done, it worked great! I believe this will only work in the .NET framework 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;
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM