我愿意报告密集型任务(I / O)的进度。我一直在阅读所有方法,界面,backGroundWorker,Progress,但没有人包括任何类型的额外信息,如任务的当前阶段。所以我写了这个方法,如果你能给我任何反馈,建议或评论,我会很高兴。我正在winforms 4.0项目中工作。
这是任务
class _ThreadTest
{
public static void ReporteProgreso(out int p, out string stage)
{
p = 0;
stage = "";
for (int i = 0; i < 10; i++)
{
System.Threading.Thread.Sleep(500);
p++;
switch (p)
{
case 0: stage = "init"; break;
case 1: stage = "Loading Data"; break;
case 2: stage = "Parsing Data"; break;
case 3: stage = "Checking"; break;
case 4: stage = "Inserting n Records"; break;
case 5: stage = "10%"; break;
case 6: stage = "50%"; break;
case 7: stage = "70%"; break;
case 8: stage = "100%"; break;
case 9: stage = "finish"; break;
default:
break;
}
}
}
}
以下是我称之为
的方式 static void Main()
{
//Reportar progreson con OUT
int p = 0;
string stage = "";
_ThreadTest t = new _ThreadTest();
Thread oThread = new Thread( () => _ThreadTest.ReporteProgreso(out p,out stage) ) ;
oThread.Start();
int tmp = 0;
while (oThread.IsAlive)
{
if (tmp != p)
{
Console.WriteLine(stage);
tmp = p;
}
}
Console.ReadKey();
}
}
是否有任何有趣的测试,更好的方法来实现这一目标?由于这种方法对我有用,因此在某些类型的环境中使用它可能不安全。
答案 0 :(得分:2)
BackgroundWorker.ReportProgress正是您正在尝试做的事情。第二个参数是包含自定义进度报告的对象。
第二个参数位于传递给UserState
事件处理程序的ProgressChangedEventArgs中的ProgressChanged
属性中。
BackgroundWorker MSDN主题有一个很好的例子。该示例中唯一缺少的是如何使用UserState
。这是一个对象,所以你需要施放它。因此,如果您的ReportProgress
电话是:
ReportProgress(1, "Loading data");
然后在你的ProgressChanged
事件处理程序中,你将它转换回字符串:
// This event handler updates the progress.
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
resultLabel.Text = (string)e.UserState
}
答案 1 :(得分:1)
我找到了一种符合我需求的方法
在我昂贵的任务中,我用这样的东西来处理他的舞台
public static class ExpensiveTasks
{
public static IEnumerable<KeyValuePair<String, int>> ExpensiveTask1(int sleepTime)
{
for (int i = 1; i <= 100; i++)
{
System.Threading.Thread.Sleep(sleepTime);
yield return new KeyValuePair<String, int>("Reporting Progress", i);
}
}
}
然后从调用它的方法,使用像这样的BackGroundWorker DoWork事件
void bW_DoWork(object sender, DoWorkEventArgs e)
{
//var args = e.Argument;
BackgroundWorker _bw = sender as BackgroundWorker;
foreach (var report in ExpensiveTasks.ExpensiveTask1(100))
{
if (_bw.CancellationPending == true)
{
e.Cancel = true;
return;
}
_bw.ReportProgress(report.Value,report.Key);
}
e.Result = "The End";
}
通过这种方法,我可以保持我的分层结构 当然,我可以以某种方式将BWWorker的引用发送到昂贵的任务,但也许它将在另一层或模块下。因此,至少以这种方式来做这件事,一直在为我工作。
:)