我正在试图弄清楚线程框架2.0在Windows移动设备(6.0)上的线程是如何工作的。现在我正在尝试制作一个进度条,因为它是最基本的东西之一,基本上在我发现的每个教程中。
从普通的Windows窗体 - 我以前用过的应用程序:
for (int i = 0; i < 10; i++)
{
myProgressBar.BeginInvoke(
new Action(() =>
{
myProgressBar.Value = i;
Thread.Sleep(100);
}
));
}
但我在new Action(()...
收到错误:
类型“
System.Action<T>
”(通用)的用法需要1-Type参数
(翻译自德语)
我似乎无法使用Action()
,只有Action<T>()
。但我不知道参数T
应该是什么或者给Action<T>()
提供什么参数。
答案 0 :(得分:1)
首先,代码可以执行的并不完全等待它,因为您在i
变量上使用了闭包,为了正确的工作,您应该将i
复制到局部变量。此外,您可以简化代码,而不是创建Action
对象,而是use simple lambda expression here, and convert it to Action
。
所以你的最终代码可能是这样的(为增量和var
关键字添加了一些小的修正):
for (var i = 0; i < 10; ++i)
{
var localI = i;
myProgressBar.BeginInvoke(
(Action)(() =>
{
myProgressBar.Value = localI;
Thread.Sleep(100);
}
));
}
由于非泛型类不适合您,您可以将传递给BeginInvoke
的方法转换为标准库中的某个委托,例如MethodInvoker
(在.NET Framework Client Profile中受支持
),并且不使用lambda,而是使用delegate
关键字来简化代码:
for (var i = 0; i < 10; ++i)
{
var localI = i;
myProgressBar.BeginInvoke(
(MethodInvoker) delegate ()
{
myProgressBar.Value = localI;
Thread.Sleep(100);
}
);
}
但是我希望您注意Thread.Sleep
这里将冻结UI线程,而不是后台线程,因为您正在调用目标线程上的Action
。 / strong>所以你最好把这些代码从UI更新中删除:
for (var i = 0; i < 10; ++i)
{
var localI = i;
myProgressBar.BeginInvoke((MethodInvoker) delegate ()
{
myProgressBar.Value = localI;
});
Thread.Sleep(100);
}
答案 1 :(得分:1)
在寻找@ MethodInvoker
的替代方案时,我发现了一种适用于紧凑框架的方法:
for (int i = 0; i < 10; i++)
{
var localI = i;
myProgressBar.BeginInvoke(
(ThreadStart)delegate()
{
myProgressBar.Value = localI;
}
);
Thread.Sleep(100);
}