我有Dictionary< string, Action[] >
,我想创建一个任务列表,我已编写此代码来创建将连续执行的任务列表。
var TaskList = new List<Task>();
foreach (var item in this.Values) {
if (TaskList.Count == 0) {
var task = new Task(item[0]);
var LogAct = task.ContinueWith((t) => item[1](), this.TokenCanc, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Default);
TaskList.AddRange(new[] { task, LogAct });
}
else {
var task = TaskList[TaskList.Count - 1].ContinueWith((t) => item[0](), this.TokenCanc, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Default);
var LogAct = task.ContinueWith((t) => item[1](), this.TokenCanc, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Default);
TaskList.AddRange(new[] { task, LogAct });
}
}
return TaskList;
}
现在在此之后,要开始我的连续任务,我打电话:
TaskList[0].Start();
我本来期望执行从1°任务开始到最新任务,但遗憾的是并非如此。
示例:
我将动作添加到我的词典:
ActionsLog.Add("T1", new Action[] { () => {
Console.WriteLine("Test1");Thread.Sleep(2000);}, () => Console.WriteLine("LogTest1") });
ActionsLog.Add("T2", new Action[] { () => {
Console.WriteLine("Test2");Thread.Sleep(2000);}, () => Console.WriteLine("LogTest2") });
ActionsLog.Add("T3", new Action[] { () => {
Console.WriteLine("Test3");Thread.Sleep(2000);}, () => Console.WriteLine("LogTest3") });
ActionsLog.Add("T4", new Action[] { () => {
Console.WriteLine("Test4");Thread.Sleep(2000);}, () => Console.WriteLine("LogTest4") });
ActionsLog.Add("T5", new Action[] { () => {
Console.WriteLine("Test5");Thread.Sleep(2000);}, () => Console.WriteLine("LogTest5") });
ActionsLog.Add("T6", new Action[] { () => {
Console.WriteLine("Test6"); Thread.Sleep(2000); }, () => Console.WriteLine("LogTest6") });
在TaskList [0]之后.Start()我得到输出:
Test1
LogTest6
Test6
LogTest6
Test6
LogTest6
Test6
LogTest6
Test6
LogTest6
Test6
LogTest6
我可能没有采取正确的方法,但我怎样才能解决我的问题?
答案 0 :(得分:0)
不确定你想做什么,但是
Task.Factory.StartNew(()=>{
foreach(var action in this.Values.SelectMany(x=>x))
action();
});
希望它有所帮助。
或者
var d = new Dictionary<string,Action[]>(); var origin = new Task(() => { }); var runner = origin; foreach (var action in d.Values.SelectMany(x=>x)) { runner = runner.ContinueWith(prev => action()); } origin.Start();
好的,完成工作样本。只需复制并粘贴。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var ActionsLog = new Dictionary<string, Action[]>();
ActionsLog.Add("T1", new Action[]
{
() =>
{
Console.WriteLine("Test1");
Thread.Sleep(2000);
},
() => Console.WriteLine("LogTest1")
});
ActionsLog.Add("T2", new Action[] { () => {
Console.WriteLine("Test2");Thread.Sleep(2000);}, () => Console.WriteLine("LogTest2") });
ActionsLog.Add("T3", new Action[] { () => {
Console.WriteLine("Test3");Thread.Sleep(2000);}, () => Console.WriteLine("LogTest3") });
ActionsLog.Add("T4", new Action[] { () => {
Console.WriteLine("Test4");Thread.Sleep(2000);}, () => Console.WriteLine("LogTest4") });
ActionsLog.Add("T5", new Action[] { () => {
Console.WriteLine("Test5");Thread.Sleep(2000);}, () => Console.WriteLine("LogTest5") });
ActionsLog.Add("T6", new Action[]
{
() =>
{
Console.WriteLine("Test6");
Thread.Sleep(2000);
},
() => Console.WriteLine("LogTest6")
});
var origin = Task.Factory.StartNew(() => { });
var runner = origin;
foreach (var action in ActionsLog.Values.SelectMany(x => x))
{
runner = runner.ContinueWith(prev => action());
}
origin.Wait();
Console.ReadLine();
}
}
}
最后。 在单独的函数中排除执行逻辑
public static void ExecuteActions(Action[] actions) { var origin = new Task(() => { }); var runner = origin; foreach (var action in actions) { runner = runner.ContinueWith(prev => action()); } origin.Start(); origin.Wait(); }
并尝试使用不同的Action数组调用它。它应该工作。如果它不适合您,那么您的数据就会出现问题。
答案 1 :(得分:0)
我做的几乎一样,而且有效..
void Main()
{
var actionlog = new Dictionary<string, Action[]>();
actionlog.Add("T1", new Action[] { () => {
Console.WriteLine("Test1");Thread.Sleep(2000);}, () => Console.WriteLine("LogTest1") });
actionlog.Add("T2", new Action[] { () => {
Console.WriteLine("Test2");Thread.Sleep(2000);}, () => Console.WriteLine("LogTest2") });
actionlog.Add("T3", new Action[] { () => {
Console.WriteLine("Test3");Thread.Sleep(2000);}, () => Console.WriteLine("LogTest3") });
actionlog.Add("T4", new Action[] { () => {
Console.WriteLine("Test4");Thread.Sleep(2000);}, () => Console.WriteLine("LogTest4") });
actionlog.Add("T5", new Action[] { () => {
Console.WriteLine("Test5");Thread.Sleep(2000);}, () => Console.WriteLine("LogTest5") });
actionlog.Add("T6", new Action[] { () => {
Console.WriteLine("Test6"); Thread.Sleep(2000); }, () => Console.WriteLine("LogTest6") });
var task = GetTaskChain(actionlog);
task.Start();
}
public Task GetTaskChain(Dictionary<string, Action[]> actionlog)
{
CancellationToken token = new CancellationToken();
var TaskList = new List<Task>();
foreach (var item in actionlog.Values)
{
if (TaskList.Count == 0)
{
var task = new Task(item[0]);
var LogAct = task.ContinueWith((t) => item[1](), token, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Default);
TaskList.AddRange(new[] { task, LogAct });
}
else
{
var task = TaskList[TaskList.Count - 1].ContinueWith((t) => item[0](), token, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Default);
var LogAct = task.ContinueWith((t) => item[1](), token, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Default);
TaskList.AddRange(new[] { task, LogAct });
}
}
return TaskList[0];
}
答案 2 :(得分:0)
它看起来像一个闭包问题。
看看你的编译器
在旧版本foreach
循环中,请保留对最后一个代理的引用
因此,例如,此代码将为旧编译器版本打印3 3 3
,为新版本打印1 2 3
。
var numbers = new int[] { 1, 2, 3 };
var actions = new List<Action>();
foreach (var number in numbers)
actions.Add(() => Console.WriteLine(number));
foreach (var action in actions)
action();
为避免这种情况,如果使用MS编译器,则编译器的版本应高于4.0.30319.1
,如果使用Mono,则编译器的版本应高于2.4.4
。
您可以找到更多信息here和here。
答案 3 :(得分:0)
我有Kote建议我的解决方案。
对于编译器版本v4.0.303191,问题是“ClosureAndForeach”。 代码解决方案是:
var list = new List<Action>();
foreach (int i in Enumerable.Range(1, 10)) {
DisplayClass c = new DisplayClass();
c.i = i;
list.Add(c.getAct());
}
foreach (Action action in list)
action();
和密封班的代码..
private sealed class DisplayClass {
public int i;
public Action getAct() {
return () => Console.WriteLine(i);
}
public void Action() {
Console.WriteLine(i);
}
}
全部谢谢!