我正在传输文件,并希望进度条显示每个文件的实际进度。这适用于15兆以下的文件但文件大于这个似乎导致我的应用程序冻结。如果我没有为进度条调用此代码,则这些较大的文件传输正常。
我已经尝试过各种不同的方法来处理代表但没有运气。相反,它们适用于较小的文件,但不适用较大的文件。
一些有效的例子......
pbFileProgress.Invoke((MethodInvoker)
delegate
{
pbFileProgress.Value = args.PercentDone;
});
此外,这组方法适用于较小的文件。
private delegate void SetProgressBarCallback(int percentDone);
public void UpdateProgressBar(object send, UploadProgressArgs args)
{
if (pbFileProgress.InvokeRequired)
{
var d = new SetProgressBarCallback(ProgressBarUpdate);
BeginInvoke(d, new object[] { args.PercentDone });
}
else
{
ProgressBarUpdate(args.PercentDone);
}
}
public void ProgressBarUpdate(int percentDone)
{
pbFileProgress.Value = percentDone;
}
但是,如果我尝试更大的文件,一切都会冻结。
答案 0 :(得分:2)
尽管缺乏背景,但这是一个有效的例子。 BeginInvoke或Invoke方法最多只调用100次。
Task.Factory.StartNew(() =>
{
using (var source = File.OpenRead(@"D:\Temp\bbe.wav"))
using (var destination = File.Create(@"D:\Temp\Copy.wav"))
{
var blockUnit = source.Length / 100;
var total = 0L;
var lastValue = 0;
var buffer = new byte[4096];
int count;
while ((count = source.Read(buffer, 0, buffer.Length)) > 0)
{
destination.Write(buffer, 0, count);
total += count;
if (blockUnit > 0 && total / blockUnit > lastValue)
{
this.BeginInvoke(
new Action<int>(value => this.progressBar1.Value = value),
lastValue = (int)(total / blockUnit));
}
}
this.BeginInvoke(
new Action<int>(value => this.progressBar1.Value = value), 100);
}
});
答案 1 :(得分:1)
在后台线程和前台线程之间进行通信时,此问题非常常见:后台线程正在发送前台线程太多更新。
前台线程处理更新,绘图和用户输入,因此当有太多更新时,UI会冻结以尝试赶上。
显然,如果后台线程继续发送更新,那么在后台任务完成后,即使也可以备份前台!
此问题有多种解决方案,但我最强烈的建议是在前台线程中使用Timer
来轮询后台进度并更新用户界面。
使用Timer
:
Timer
的频率可以设置为“合理”值,例如250毫秒(每秒4次更新),以便进度顺利但不占用整个处理器与往常一样,在线程之间传递进度时,线程安全很重要。在这种情况下,使用简单的32位int
值是线程安全的,但使用64位double
在32位计算机上不是线程安全的。
答案 2 :(得分:0)
您可以根据UI元素进行调用。例如:
private delegate void InvokeUpdateProgressBar(object send, UploadProgressArgs args);
private int _PercentDone = -1;
public void UpdateProgressBar(object send, UploadProgressArgs args)
{
if(_PercentDone != args.PercentDone)
{
if (pbFileProgress.InvokeRequired)
{
pbFileProgress.Invoke(
new InvokeUpdateProgressBar(UpdateProgressBar),
new object[] { send, args });
}
else
{
ProgressBarUpdate(args.PercentDone);
}
_PercentDone = args.PercentDone;
}
}
否则我会建议Aaron McIver做了什么并使用BackgroundWorker类。 有关使用BackgroundWorker类更新进度条的详细信息,请参阅示例here
<强>更新强>
看起来你不是唯一有这个问题的人。请在此处查看Amazon s3 Transferutility.Upload hangs in C#。肯特还指出:If you read in about the S3 forums you'll find many people having similar issues