Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 循环中的System.threading.timer产生意外结果_C#_Multithreading_Delegates_Timer - Fatal编程技术网

C# 循环中的System.threading.timer产生意外结果

C# 循环中的System.threading.timer产生意外结果,c#,multithreading,delegates,timer,C#,Multithreading,Delegates,Timer,我有一个创建计时器的循环。我有两个问题 第一个问题是如何以“fire-and-forget”的方式运行命令,这样我就可以调用它,它将在另一个线程中自己执行,并将自己发回API。如果刷新属性设置为0,则会出现这种情况 第二个是在循环的下一次迭代中替换循环中的参数(check.key)。当委托激发该方法时,将向其传递替换的值,而不是原始指定的值 在下面的示例中,值被正确分配,但当代理激发时,它总是使用参数“3”激发 字典mydict中充满了来自远程API的数据 classtocall和methodt

我有一个创建计时器的循环。我有两个问题

第一个问题是如何以“fire-and-forget”的方式运行命令,这样我就可以调用它,它将在另一个线程中自己执行,并将自己发回API。如果刷新属性设置为0,则会出现这种情况

第二个是在循环的下一次迭代中替换循环中的参数(check.key)。当委托激发该方法时,将向其传递替换的值,而不是原始指定的值

在下面的示例中,值被正确分配,但当代理激发时,它总是使用参数“3”激发

字典mydict中充满了来自远程API的数据

classtocall和methodtocall并不总是相同的。它们可以被多次调用,因为提供的键允许访问测试类中的更多参数。测试类中的refresh属性定义计时器时间

我希望这是有意义的

代码(快速模拟,因为我的真实代码很大):

公共类测试
{
公共字符串类调用;
公共字符串方法调用;
公共字符串唯一密钥;
公众长时间刷新;
//更多,但已移除,用于取样
公共测试(字符串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
}