C# 永久操作多任务
我正在研究多任务处理,我用windows窗体找到了一个非常简单的解决方案。 我有一个名为“车”的对象列表: 我想在“多会话(任务)”中做一些工作 假设我的“汽车”有两种方法:C# 永久操作多任务,c#,multitasking,C#,Multitasking,我正在研究多任务处理,我用windows窗体找到了一个非常简单的解决方案。 我有一个名为“车”的对象列表: 我想在“多会话(任务)”中做一些工作 假设我的“汽车”有两种方法:StartFullEngine()和GoDrive(),这是我在CarBusiness.cs中编写的,我想将一些消息输出到richtextbox。我有一个固定的10辆车的列表,会话的数量将代表上街的车的数量(几乎在同一时间),但是当他们在街上时,他们总是做同样的事情。即: 启动fullengine()。启动后,转到下一步:
StartFullEngine()
和GoDrive()
,这是我在CarBusiness.cs
中编写的,我想将一些消息输出到richtextbox
。我有一个固定的10辆车的列表,会话的数量将代表上街的车的数量(几乎在同一时间),但是当他们在街上时,他们总是做同样的事情。即:
启动fullengine()
。启动后,转到下一步:GoDrive()
。这可以异步执行,而另一个任务将从列表中选择下一辆车并返回到步骤1。它将永远停留在这个循环中,但不会耗尽会话public class CarBusiness
{
private RichTextBox _richTextBox;
private static readonly object syncLock = new object();
private Car _carToRun;
private Random random;
public CarBusiness(Car car, RichTextBox richTextBox)
{
_carToRun = car;
_richTextBox = richTextBox;
random = new Random();
}
private void OutputMessage(string msg)
{
lock (syncLock)
{
_richTextBox.BeginInvoke((Action)(() =>
{
_richTextBox.AppendText($"#{_carToRun.Id}: [{DateTime.Now.Hour.ToString("D2")}:{DateTime.Now.Minute.ToString("D2")}:{DateTime.Now.Second.ToString("D2")}] - {msg}\r\n");
}));
}
}
public Task StartFullEngine()
{
return Task.Run(async () =>
{
var start = DateTime.Now;
await Task.Delay(random.Next(1000, 10000));
var end = DateTime.Now;
TimeSpan timeDiff = start - end;
var readableDiff = string.Format(
"{0:D2} hrs, {1:D2} mins, {2:D2} secs",
timeDiff.Hours, timeDiff.Minutes, timeDiff.Seconds);
OutputMessage($"Full engined finished. Time ellapsed: {readableDiff}");
});
}
public Task GoDrive()
{
return Task.Run(async () =>
{
var start = DateTime.Now;
await Foo();
Boo().Wait();
var end = DateTime.Now;
TimeSpan timeDiff = start - end;
var readableDiff = string.Format(
"{0:D2} hrs, {1:D2} mins, {2:D2} secs",
timeDiff.Hours, timeDiff.Minutes, timeDiff.Seconds);
OutputMessage($"GoDrive() finished. Time ellapsed: {readableDiff}");
});
}
private Task Foo()
{
return Task.Run(async () =>
{
//long operation
OutputMessage($"Running Foo()...");
await Task.Delay(random.Next(1000, 3000));
OutputMessage($"Foo() ended!");
});
}
private Task Boo()
{
return Task.Run(async () =>
{
OutputMessage($"Running Boo()...");
await Task.Delay(random.Next(10000, 30000));
OutputMessage($"Boo() ended!");
});
}
}
public class CarDao
{
public List<Car> GetListOfCar()
{
var list = new List<Car>();
for (int i = 1; i <= 10; i++)
list.Add(new Car { Id = i, Status = Status.Standby });
return list;
}
}
public partial class Form1 : Form
{
private List<Car> listOfCars;
private object objInstances = new object();
public Form1()
{
InitializeComponent();
}
private Task<Car> GetNextCar()
{
return Task.Run(() =>
{
lock (objInstances)
{
//Need a logic to prioritize getting cars that have never "run" before
var nextCar = listOfCars.Where(x => x.Status != Status.Running).SkipWhile(x => x.Status == Status.Finished).FirstOrDefault();
return nextCar;
}
});
}
private Task<List<Car>> GetInstances(Status statusCar)
{
return Task.Run(() =>
{
lock (objInstances)
{
return listOfCars.Where(x => x.Status == statusCar).ToList();
}
});
}
private async void button1_Click(object sender, EventArgs e)
{
var carDao = new CarDao();
//NumericUpDown value
var maxSessions = numberOfSessions.Value;
//fixed list of cars
listOfCars = carDao.GetListOfCar();
//Never stop running
while (true)
{
var runningInstances = GetInstances(Status.Running).Result;
for (int i = runningInstances.Count(); i < maxSessions; i++)
{
var carToRun = GetNextCar().Result;
carToRun.Status = Status.Running;
var carBusiness = new CarBusiness(carToRun, richTextBox);
Task.Run(() =>
{
//First thing: StartFullEngine()
carBusiness.StartFullEngine().Wait();
}).Wait();
//After started Engine, GoDrive() can run asynchronously.
await Task.Run(() =>
{
carBusiness.GoDrive().Wait();
carToRun.Status = Status.Finished;
});
//Next loop;
}
//logic to wait some tasks get done to start again
runningInstances = GetInstances(Status.Running).Result;
if (runningInstances.Count() == maxSessions)
Task.Delay(20000).Wait();
}
}
}
CarDao.cs:
public class CarBusiness
{
private RichTextBox _richTextBox;
private static readonly object syncLock = new object();
private Car _carToRun;
private Random random;
public CarBusiness(Car car, RichTextBox richTextBox)
{
_carToRun = car;
_richTextBox = richTextBox;
random = new Random();
}
private void OutputMessage(string msg)
{
lock (syncLock)
{
_richTextBox.BeginInvoke((Action)(() =>
{
_richTextBox.AppendText($"#{_carToRun.Id}: [{DateTime.Now.Hour.ToString("D2")}:{DateTime.Now.Minute.ToString("D2")}:{DateTime.Now.Second.ToString("D2")}] - {msg}\r\n");
}));
}
}
public Task StartFullEngine()
{
return Task.Run(async () =>
{
var start = DateTime.Now;
await Task.Delay(random.Next(1000, 10000));
var end = DateTime.Now;
TimeSpan timeDiff = start - end;
var readableDiff = string.Format(
"{0:D2} hrs, {1:D2} mins, {2:D2} secs",
timeDiff.Hours, timeDiff.Minutes, timeDiff.Seconds);
OutputMessage($"Full engined finished. Time ellapsed: {readableDiff}");
});
}
public Task GoDrive()
{
return Task.Run(async () =>
{
var start = DateTime.Now;
await Foo();
Boo().Wait();
var end = DateTime.Now;
TimeSpan timeDiff = start - end;
var readableDiff = string.Format(
"{0:D2} hrs, {1:D2} mins, {2:D2} secs",
timeDiff.Hours, timeDiff.Minutes, timeDiff.Seconds);
OutputMessage($"GoDrive() finished. Time ellapsed: {readableDiff}");
});
}
private Task Foo()
{
return Task.Run(async () =>
{
//long operation
OutputMessage($"Running Foo()...");
await Task.Delay(random.Next(1000, 3000));
OutputMessage($"Foo() ended!");
});
}
private Task Boo()
{
return Task.Run(async () =>
{
OutputMessage($"Running Boo()...");
await Task.Delay(random.Next(10000, 30000));
OutputMessage($"Boo() ended!");
});
}
}
public class CarDao
{
public List<Car> GetListOfCar()
{
var list = new List<Car>();
for (int i = 1; i <= 10; i++)
list.Add(new Car { Id = i, Status = Status.Standby });
return list;
}
}
public partial class Form1 : Form
{
private List<Car> listOfCars;
private object objInstances = new object();
public Form1()
{
InitializeComponent();
}
private Task<Car> GetNextCar()
{
return Task.Run(() =>
{
lock (objInstances)
{
//Need a logic to prioritize getting cars that have never "run" before
var nextCar = listOfCars.Where(x => x.Status != Status.Running).SkipWhile(x => x.Status == Status.Finished).FirstOrDefault();
return nextCar;
}
});
}
private Task<List<Car>> GetInstances(Status statusCar)
{
return Task.Run(() =>
{
lock (objInstances)
{
return listOfCars.Where(x => x.Status == statusCar).ToList();
}
});
}
private async void button1_Click(object sender, EventArgs e)
{
var carDao = new CarDao();
//NumericUpDown value
var maxSessions = numberOfSessions.Value;
//fixed list of cars
listOfCars = carDao.GetListOfCar();
//Never stop running
while (true)
{
var runningInstances = GetInstances(Status.Running).Result;
for (int i = runningInstances.Count(); i < maxSessions; i++)
{
var carToRun = GetNextCar().Result;
carToRun.Status = Status.Running;
var carBusiness = new CarBusiness(carToRun, richTextBox);
Task.Run(() =>
{
//First thing: StartFullEngine()
carBusiness.StartFullEngine().Wait();
}).Wait();
//After started Engine, GoDrive() can run asynchronously.
await Task.Run(() =>
{
carBusiness.GoDrive().Wait();
carToRun.Status = Status.Finished;
});
//Next loop;
}
//logic to wait some tasks get done to start again
runningInstances = GetInstances(Status.Running).Result;
if (runningInstances.Count() == maxSessions)
Task.Delay(20000).Wait();
}
}
}
我可以证实,这个问题还不够清楚。如果您可以指定您的期望值,以及这与您的期望值不符的程度,这将有助于我们了解问题的根源,而不必猜测您的意图。@afarley刚刚在预期输出中编辑了问题。您想在这里完成什么还不是很清楚。您的代码中至少有几个突出的问题,例如,您如何通过每次单击按钮来覆盖您的汽车参考列表。@StevePy我认为我缺乏正确的词语来表达自己。我想让它们并行运行。我可以确认这个问题还不够清楚。如果您可以指定您的期望值,以及这与您的期望值不符的程度,这将有助于我们了解问题的根源,而不必猜测您的意图。@afarley刚刚在预期输出中编辑了问题。您想在这里完成什么还不是很清楚。您的代码中至少有几个突出的问题,例如,您如何通过每次单击按钮来覆盖您的汽车参考列表。@StevePy我认为我缺乏正确的词语来表达自己。我想让它们并行运行。