我正在编写一个与第三方程序交互的程序.该第三方程序允许用户制作可以在第三方程序中执行步骤记录的按钮.但!这些按钮还可以运行用户定义的批处理文件.因此,我使用此功能通过创建文件和检查这些文件是否存在来与我的程序进行交互.
我的程序包含两个类,一个Actionlistener和一个Actionperformer.actionperformer包含一个包含可能操作的枚举.
read函数如下所示:
static public void CheckForActions()
{
//For every action in the Enum
foreach (ActionPerformer.PossibleActions action in Enum.GetValues(typeof(ActionPerformer.PossibleActions)))
{
//If a file exists with the same name as the current action
if (File.Exists(_location + action.ToString()))
{
//Delete "message" and create a new thread to perform this action.
File.Delete(_location + action);
Thread _t = new Thread(() =>
{
new ActionPerformer(action);
});
_t.SetApartmentState(ApartmentState.STA);
_t.Start();
//Add thread to list so they can be joined propperly
_list.Add(_t);
//Write information to log
Logger.LogInfo(_t, "Starting new action: " + action.ToString(), DateTime.Now);
}
}
//If there are items in the list
if (_list.Count > 0)
{
//Dispose every thread once its done.
foreach (Thread _t in _list)
{
_t.Join();
Logger.LogInfo("Finishing action.", DateTime.Now);
}
_list.Clear();
}
}
Run Code Online (Sandbox Code Playgroud)
ActionPerformer类看起来像这样:
class ActionPerformer
{
public enum PossibleActions
{
action1,
action2,
}
public ActionPerformer(PossibleActions action)
{
Logger.LogInfo(action.ToString(), DateTime.Now);
}
}
Run Code Online (Sandbox Code Playgroud)
因此,当我使用action1作为参数运行程序,并读取记录器输出时,我应该得到这样的结果:
Starting new action: action1 [13:30:05]
action1 [13:30:05]
Finishing action. [13:30:05]
Run Code Online (Sandbox Code Playgroud)
但是我第一次调用CheckForActions时总是将其作为输出:
Starting new action: action1 [13:30:05]
action2 [13:30:05] //Notice how it is not action1?
Finishing action. [13:30:05]
Run Code Online (Sandbox Code Playgroud)
我第二次调用CheckForActions,一切都按预期工作......
有谁知道发生了什么?
问题不在于Enum.GetValues,而在于你如何传递价值.
Thread _t = new Thread(() =>
{
new ActionPerformer(action);
});
Run Code Online (Sandbox Code Playgroud)
这个创建了一个新的闭包,它包含对变量动作的REFERENCE(因此,当'action'值改变时,线程会看到新的值.
您可以将"action"作为参数传递给Thread.
Thread _t = new Thread((act) =>
{
new ActionPerformer(act);
});
_t.Start(action);
Run Code Online (Sandbox Code Playgroud)
或者,使用其他人建议的方法(在foreach的主体中创建局部变量,并在闭包中访问它.)
如果您在闭包中访问修改后的变量,我认为Resharper会发出警告.
顺便说一句,不要用下划线为局部变量加前缀.它不遵循通常的c#标准.