使用Action <T>创建任务

alw*_*ing 8 .net c# task-parallel-library

我不知何故觉得我错过了一些基本的东西.这是我的问题.

我正在尝试创建一个System.Threading.Tasks.Task实例来执行接受某种类型参数的操作.我以为我可以做点什么

void DoWork(MyClass obj) {} //My action that accepts a parameter of type 'MyClass'

MyClass obj = new MyClass(); 
Action<MyClass> action = DoWork; //action that points to the method
Task task = new Task(action,obj); //task that would execute 'DoWork' with 'obj' as the parameter when I call Start.
Run Code Online (Sandbox Code Playgroud)

显然这不会编译.看来我只能使用一个Action<object>而不是Action<T>一个任务,然后在我的方法中将'对象'转换为T.

如何才能最有效,最有效地实现我的目标?

cuo*_*gle 6

您也可以直接使用:

MyClass obj = new MyClass();
Task task = Task.Run(() => DoWork(obj));
Run Code Online (Sandbox Code Playgroud)

  • 只是提一下:这有一个稍微不同的含义。如果您在启动任务之前更改*变量* obj`,甚至在`Task`逻辑调用委托之前更改,`DoWork`将处理新对象。这可能会导致很难跟踪的错误。一个典型的情况是,如果您在循环中使用它 `foreach(MyClass o in myObjList) { (new Task(()=&gt;DoWork(o))).Start(); }`。 (2认同)

Mar*_*ner 5

你可以用

Action<Object> action = o => DoWork((MyClass)o);
Task task = new Task(action, obj);
Run Code Online (Sandbox Code Playgroud)

如果您使用的是.NET 4.0或更高版本,则可以使用Contravariance来实现您的目标,而无需引入新的委托

//INCORRECT Code, casts InvalidCastException at runtime
Action action = DoWork;
Task task = new Task((Action)action, obj);

编辑:

感谢@svick您指出的是,第二个选项是不正确的:我太忙了梳理,动作是否是同向或逆变(其实它是逆变,我是对这个至少)我监督,即我需要协方差在这种情况下.

逆变意味着你可以做到

Action<object> action1 = someAction;
Action<SubClass> action2 = action1;
Run Code Online (Sandbox Code Playgroud)

没有明确的铸造.