我想在带有Marquee样式的表单上添加ProgressBar,以向用户显示正在进行的操作。在耗时的操作过程中,表单不会更新,因此ProgressBar也会冻结"。
我查了几篇关于BackgroundWorker的帖子,但就我而言,操作并没有报告进度,这就是我需要Marquee栏的原因。
感谢任何帮助或代码段。
注意:我需要使用.NET 4.0(支持XP),所以我不能使用Task.Run :(
button1_Click(object sender, EventArgs e)
{
progressBar1.Style = ProgressBarStyle.Marquee;
progressBar1.MarqueeAnimationSpeed = 50;
// INSERT TIME CONSUMING OPERATIONS HERE
// THAT DON'T REPORT PROGRESS
Thread.Sleep(10000);
progressBar1.MarqueeAnimationSpeed = 0;
progressBar1.Style = ProgressBarStyle.Blocks;
progressBar1.Value = progressBar1.Minimum;
}
答案 0 :(得分:8)
我查了几篇关于BackgroundWorker的帖子,但就我而言 操作不报告进度,这就是我需要一个Marquee栏的原因。
您可以使用BackgroundWorker,只是不要使用它的“进度”部分。这两件事并不相互排斥......
示例:
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
progressBar1.Style = ProgressBarStyle.Marquee;
progressBar1.MarqueeAnimationSpeed = 50;
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += bw_DoWork;
bw.RunWorkerCompleted += bw_RunWorkerCompleted;
bw.RunWorkerAsync();
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
// INSERT TIME CONSUMING OPERATIONS HERE
// THAT DON'T REPORT PROGRESS
Thread.Sleep(10000);
}
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
progressBar1.MarqueeAnimationSpeed = 0;
progressBar1.Style = ProgressBarStyle.Blocks;
progressBar1.Value = progressBar1.Minimum;
button1.Enabled = true;
MessageBox.Show("Done!");
}
答案 1 :(得分:0)
你仍然需要在不同的线程上运行耗时的工作......你在UI线程上运行它意味着UI没有机会进行任何UI更新(因此你见证了冻结)! / p>
您应该考虑使用# Root logger option
log4j.rootLogger=DEBUG, stdout, file
# Redirect log messages to console
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
# Redirect log messages to a log file, support file rolling.
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=logs/log4j-MyFirstClass.log
log4j.appender.file.MaxFileSize=5MB
log4j.appender.file.MaxBackupIndex=10
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
代替Task<>
。
有关BackgroundWorker
的详细信息,请参阅https://msdn.microsoft.com/en-us/library/hh195051%28v=vs.110%29.aspx。
如果您无法使用Task<>
,则应恢复为Task<>
并使用BackgroundWorker
事件停止选取框并将程序移至下一个操作。
答案 2 :(得分:0)
解决。但是,我认为这是处理它的最不优雅的方式。
button1_Click(object sender, EventArgs e)
{
progressBar1.Style = ProgressBarStyle.Marquee;
progressBar1.MarqueeAnimationSpeed = 50;
Task task = Task.Factory.StartNew(() =>
{
// INSERT TIME CONSUMING OPERATIONS HERE
// THAT DON'T REPORT PROGRESS
Thread.Sleep(10000);
});
while (!task.IsCompleted)
{
Application.DoEvents();
Thread.Sleep(1);
}
progressBar1.MarqueeAnimationSpeed = 0;
progressBar1.Style = ProgressBarStyle.Blocks;
progressBar1.Value = progressBar1.Minimum;
}
答案 3 :(得分:0)
首选解决方案
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
progressBar1.Style = ProgressBarStyle.Marquee;
progressBar1.MarqueeAnimationSpeed = 50;
Task.Factory.StartNew(() => {
// INSERT TIME CONSUMING OPERATIONS HERE
// THAT DON'T REPORT PROGRESS
Thread.Sleep(10000);
}, TaskCreationOptions.LongRunning).
ContinueWith(t => {
progressBar1.MarqueeAnimationSpeed = 0;
progressBar1.Style = ProgressBarStyle.Blocks;
progressBar1.Value = progressBar1.Minimum;
button1.Enabled = true;
MessageBox.Show("Done!");
}, TaskScheduler.FromCurrentSynchronizationContext());
}
P.S。为了处理可能的操作取消,该示例实例化了一个CancellationTokenSource
对象,该对象生成一个取消令牌。