我是使用回调和异步函数的新手,所以我有点不确定解决这个问题的最佳方法。
我创建了一个名为 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()
不返回值,并且我必须使用 UploadFileCompleteEventHandler 在完成上传时获取响应。 因此,我在与 SendPhoto()
和 PostFile()
相同的类中编写了一个回调函数来检索响应,在该函数上实例化了一个 UploadFileCompletedEventHandler,并将其传递给我的 PostFile()
函数。
问题是我不确定如何将响应返回SendPhoto()
函数,以便它可以解释响应并将友好的响应发送回 GUI。 以前,当一切都是同步的时,响应只是传递回堆栈,但现在,响应在几层之后返回。
现在PostFile()
无法再将其返回给我,从回调函数向SendPhoto()
返回响应的最佳方法是什么? 我想将事件处理程序回调移动到 GUI 并将UploadFileCompletedEventHandler
传递给 SendPhoto()
,这又会将其发送到 PostFile()
。 但我试图将"业务逻辑"(即解释响应(排除在 GUI 类之外。
好的,今天早上做了更多的工作,并使用"await"找到了一个非常优雅的解决方案(谢谢,穆克塔迪尔·第纳尔! 我不得不更改对 UploadFileTaskAsync(( 的调用,以便它支持 "await" 关键字,我必须用"async"装饰我的所有方法并使它们返回任务,一直回到 GUI 的按钮单击事件处理程序,但是当我完成后,它工作得很好! 我相信这仅适用于.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;
}