问题描述
是的,在这里进行了一些谷歌搜索和搜索,我发现的唯一相关问题是 this,虽然它的唯一答案没有被标记为已接受,但它已经过时且令人困惑.
Aight, did a bit of Googling and searching here, the only question I found related was this, although the only answer it had wasn't marked as accepted, is old and is confusing.
我的问题基本上就是我在标题中所说的.发生的情况是在上传过程中 GUI 冻结.我的代码:
My problem is basically what I've said in the title. What happens is that the GUI freezes while the upload is in progress. My code:
// stuff above snipped
public partial class Form1 : Form
{
WebClient wcUploader = new WebClient();
public Form1()
{
InitializeComponent();
wcUploader.UploadFileCompleted += new UploadFileCompletedEventHandler(UploadFileCompletedCallback);
wcUploader.UploadProgressChanged += new UploadProgressChangedEventHandler(UploadProgressCallback);
}
private void button1_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
string toUpload = openFileDialog1.FileName;
wcUploader.UploadFileAsync(new Uri("http://anyhub.net/api/upload"), "POST", toUpload);
}
}
void UploadFileCompletedCallback(object sender, UploadFileCompletedEventArgs e)
{
textBox1.Text = System.Text.Encoding.UTF8.GetString(e.Result);
}
void UploadProgressCallback(object sender, UploadProgressChangedEventArgs e)
{
textBox1.Text = (string)e.UserState + "\n\n"
+ "Uploaded " + e.BytesSent + "/" + e.TotalBytesToSend + "b (" + e.ProgressPercentage + "%)";
}
}
为了澄清,这是按顺序发生的:
For clarification, this is what happens in order:
- 我点击 button1
- 我选择一个文件
- GUI 停止响应,因为当我点击它时什么也没有发生
- 几秒钟后,文本框中显示了 50% Aa 并且实现了.查看我对我标记为解决方案的问题的评论
- 大约一秒钟后,GUI 没有响应,它被替换为响应
推荐答案
当然可以.
代码运行良好.
wcUploader.UploadFileAsync(...)
启动请求并继续执行,同时在 TextBox1 中更新进度,完成后我得到一些 JSON.
wcUploader.UploadFileAsync(...)
initiates the request and execution continues, meanwhile the progress is updated in TextBox1 and upon completion I get some JSON.
那是异步.如果您只是调用 wcUploader.UploadFile
,则执行将在那里阻塞,直到文件上传并且您将不会收到任何进度事件.
That is Async. If you simply called wcUploader.UploadFile
, execution would block there until the file was uploaded and you would get no progress events.
底线:
UI 不会被阻塞,会调用进度事件并实时更新 UI.
The UI is not blocked, progress events are called and UI is updated in real time.
更新:
要消除 webclient 建立 http 连接时的初始阻塞,只需在另一个线程上调用上传即可.在这种情况下,必须使用调用来防止跨线程异常:
To eliminate the initial block when the webclient is establishing the http connection, simply call the upload on another thread. In this scenario, you must use invocation to prevent cross thread exceptions:
using System;
using System.Net;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private readonly WebClient wcUploader = new WebClient();
public Form1()
{
InitializeComponent();
wcUploader.UploadFileCompleted += UploadFileCompletedCallback;
wcUploader.UploadProgressChanged += UploadProgressCallback;
}
private void UploadFileCompletedCallback(object sender, UploadFileCompletedEventArgs e)
{
// a clever way to handle cross-thread calls and avoid the dreaded
// "Cross-thread operation not valid: Control 'textBox1' accessed
// from a thread other than the thread it was created on." exception
// this will always be called from another thread,
// no need to check for InvokeRequired
BeginInvoke(
new MethodInvoker(() =>
{
textBox1.Text = Encoding.UTF8.GetString(e.Result);
button1.Enabled = true;
}));
}
private void UploadProgressCallback(object sender, UploadProgressChangedEventArgs e)
{
// a clever way to handle cross-thread calls and avoid the dreaded
// "Cross-thread operation not valid: Control 'textBox1' accessed
// from a thread other than the thread it was created on." exception
// this will always be called from another thread,
// no need to check for InvokeRequired
BeginInvoke(
new MethodInvoker(() =>
{
textBox1.Text = (string)e.UserState + "\n\n"
+ "Uploaded " + e.BytesSent + "/" + e.TotalBytesToSend
+ "b (" + e.ProgressPercentage + "%)";
}));
}
private void button1_Click(object sender, EventArgs e)
{
textBox1.Text = "";
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
button1.Enabled = false;
string toUpload = openFileDialog1.FileName;
textBox1.Text = "Initiating connection";
new Thread(() =>
wcUploader.UploadFileAsync(new Uri("http://anyhub.net/api/upload"), "POST", toUpload)).Start();
}
}
}
}
这篇关于UploadFileAsync 不是异步的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!