C# 循环中的System.threading.timer产生意外结果
我有一个创建计时器的循环。我有两个问题 第一个问题是如何以“fire-and-forget”的方式运行命令,这样我就可以调用它,它将在另一个线程中自己执行,并将自己发回API。如果刷新属性设置为0,则会出现这种情况 第二个是在循环的下一次迭代中替换循环中的参数(check.key)。当委托激发该方法时,将向其传递替换的值,而不是原始指定的值 在下面的示例中,值被正确分配,但当代理激发时,它总是使用参数“3”激发 字典mydict中充满了来自远程API的数据 classtocall和methodtocall并不总是相同的。它们可以被多次调用,因为提供的键允许访问测试类中的更多参数。测试类中的refresh属性定义计时器时间 我希望这是有意义的 代码(快速模拟,因为我的真实代码很大):C# 循环中的System.threading.timer产生意外结果,c#,multithreading,delegates,timer,C#,Multithreading,Delegates,Timer,我有一个创建计时器的循环。我有两个问题 第一个问题是如何以“fire-and-forget”的方式运行命令,这样我就可以调用它,它将在另一个线程中自己执行,并将自己发回API。如果刷新属性设置为0,则会出现这种情况 第二个是在循环的下一次迭代中替换循环中的参数(check.key)。当委托激发该方法时,将向其传递替换的值,而不是原始指定的值 在下面的示例中,值被正确分配,但当代理激发时,它总是使用参数“3”激发 字典mydict中充满了来自远程API的数据 classtocall和methodt
公共类测试
{
公共字符串类调用;
公共字符串方法调用;
公共字符串唯一密钥;
公众长时间刷新;
//更多,但已移除,用于取样
公共测试(字符串MyClass、字符串MyMethod、字符串键)
{
this.ClassToCall=MyClass;
this.MethodToCall=MyMethod;
this.UniqueKey=Key;
}
}
类运行名
{
公共静态void runmefirst(字符串键)
{//根据密钥执行一些处理
}
公共静态void runmesecond(字符串键)
{//根据密钥执行一些处理
}
公共静态void runmelast(字符串键)
{//根据密钥执行一些处理
}
}
类myclass
{
专用静态定时器[]定时器;
静态void Main()
{
字典_mydict=新字典();
_添加(“1”,新测试(“runme”、“runmefirst”、“1”);
_添加(“2”,新测试(“runme”,“runmesecond”,“2”);
_mydict.Add(“3”,新测试(“runme”、“runmelast”、“3”);
int i=0;
foreach(KeyValuePair签入\u mydict)
{
Type t=Type.GetType(check.Value.ClassToCall);
如果(t!=null)
{
MethodInfo mi=t.GetMethod(check.Value.MethodToCall);
如果(mi!=null)
{
如果(check.Value.Refresh==0)
{
mi.Invoke(null,新字符串[]{check.Key});//用于计时器部分:
您还没有显示您正在使用哪种类型的计时器(共有三种)。如果您使用的是System.Threading.Timer
或System.Timers.Timer
,那么我希望它已经在线程池中执行了
对于错误的值部分:
您正在使用一个循环:
foreach (KeyValuePair<string,Test> check in _mydict)
这是捕获变量check
,并且check
的值在每次迭代中都会更改。您将始终看到最后一个值。不过,这个值很容易修复:
foreach (KeyValuePair<string,Test> check in _mydict)
{
var copy = check;
...
// Then later...
delegate { mi.Invoke(null, new string[] { copy.Key }); },
}
foreach(KeyValuePair签入\u mydict)
{
var副本=检查;
...
//后来。。。
委托{mi.Invoke(null,新字符串[]{copy.Key});},
}
这次您将在每次迭代中捕获一个“新”局部变量,并且该局部变量的值不会改变
注意,C#5中的行为将发生变化,以允许您以前的代码在此工作
另一方面,您可以使用Delegate.CreateDelegate
直接从MethodInfo
创建一个委托,并将其传入…启动一个新线程
System.Threading.Thread mythread =
new System.Threading.Thread(new System.Threading.ThreadStart(MyFunction));
mythread .Start();
调用的函数
private void MyFunction()
{
if (InvokeRequired)
{
this.Invoke(new MethodInvoker(MyFunction));
return;
}
//DO YOUR STUFF
}
没有时间键入对此的完整响应,但您应该检查系统.Threading.Tasks
(),从Task.Factory.StartNew(()=>{/*您的fire and forget code here*/})开始;
-请参阅
System.Threading.Thread mythread =
new System.Threading.Thread(new System.Threading.ThreadStart(MyFunction));
mythread .Start();
private void MyFunction()
{
if (InvokeRequired)
{
this.Invoke(new MethodInvoker(MyFunction));
return;
}
//DO YOUR STUFF
}