出错时重试异步文件上传

本文关键字:文件 异步 重试 出错 | 更新日期: 2023-09-27 17:56:32

我正在尝试在WPF应用程序中上传文件。如果服务器响应,一切正常,但该应用程序将在具有"不安全"互联网连接的环境中使用。因此,如果第一次尝试失败,我想在短暂休息后重试上传。

我用 async/await 尝试了几件事,最终得到了以下代码。如果服务器正在运行,一切正常,但如果不是,程序在 while-循环的第二次迭代中失败并显示 ObjectDisposedException。

有什么想法吗?

private void UploadButton_Click(object sender, RoutedEventArgs e)
{
    // build content to send
    content = new MultipartFormDataContent();
    var filestream = new FileStream(filePath, FileMode.Open);
    var fileName = System.IO.Path.GetFileName(filePath);
    content.Add(new StreamContent(filestream), "file", fileName);
    content.Add(new StringContent(terminal_id.ToString()), "terminal_id");
    UploadTask(content);
    /*var task_a = new Task(() => UploadTask(content));
    task_a.Start();*/
}
private async void UploadTask(HttpContent content)
{
    bool success = false;
    int counter = 0;
    while (counter < 3 && !success)
    {
        Debug.WriteLine("starting upload");
        success = await UploadFileAsync(content);
        Debug.WriteLine("finished upload. result " + success.ToString());
        //if (!success) System.Threading.Thread.Sleep(5000);
        counter++;
    }
}
private async Task<bool> UploadFileAsync(HttpContent content)
{
    var message = new HttpRequestMessage();
    message.Method = HttpMethod.Post;
    message.Content = content;
    message.RequestUri = new Uri(target_url);
    using (HttpClient client = new HttpClient())
    {
        try
        {
            HttpResponseMessage res = await client.SendAsync(message);
            if (res.IsSuccessStatusCode) return true;
        }
        catch (HttpRequestException hre)
        {
            Debug.WriteLine(hre.ToString());
        }
        return false;
    }
}

出错时重试异步文件上传

似乎您的文件流被释放/关闭。您需要从头开始重试(content = new MultipartFormDataContent();等)。

我认为问题可能是content超出了范围? 尝试在 UploadTask 方法中创建content。 此外,可能值得从UploadTask返回一个Task<bool>,并将其缓存为类级变量(因此您不必返回 void)。

例如:

Task<bool> newTask;
private void UploadButton_Click(object sender, RoutedEventArgs e)
{
    newTask = UploadTask();
}
private async Task<bool> UploadTask()
{
bool success = false;
int counter = 0;
// build content to send
HttpContent content = new MultipartFormDataContent();
var filestream = new FileStream(filePath, FileMode.Open);
var fileName = System.IO.Path.GetFileName(filePath);
content.Add(new StreamContent(filestream), "file", fileName);
content.Add(new StringContent(terminal_id.ToString()), "terminal_id");
while (counter < 3 && !success)
{
    Debug.WriteLine("starting upload");
    success = await UploadFileAsync(content);
    Debug.WriteLine("finished upload. result " + success.ToString());
    counter++;
}
return success;
}

将内容的创建移动到 UploadFileAsync() 后,它可以工作。结果:

Task<bool> newTask;
private void UploadButton_Click(object sender, RoutedEventArgs e)
{
    newTask = UploadTask();
}
private async Task<bool> UploadTask()
{
    bool success = false;
    int counter = 0;
    while (counter < 3 && !success)
    {
        Debug.WriteLine("starting upload");
        success = await UploadFileAsync();
        Debug.WriteLine("finished upload. result " + success.ToString());
        if (!success) System.Threading.Thread.Sleep(5000);
        counter++;
    }
    return success;
}
private async Task<bool> UploadFileAsync()
{
    MultipartFormDataContent content = new MultipartFormDataContent();
    var filestream = new FileStream(filePath, FileMode.Open);
    var fileName = System.IO.Path.GetFileName(filePath);
    content.Add(new StreamContent(filestream), "file", fileName);
    content.Add(new StringContent(terminal_id.ToString()), "terminal_id");
    var message = new HttpRequestMessage();
    message.Method = HttpMethod.Post;
    message.Content = content;
    message.RequestUri = new Uri(target_url);
    using (HttpClient client = new HttpClient())
    {
        try
        {
            HttpResponseMessage res = await client.SendAsync(message);
            if (res.IsSuccessStatusCode) return true;
        }
        catch (HttpRequestException hre)
        {
            Debug.WriteLine(hre.ToString());
        }
        return false;
    }
}