我想要一种方式,让每个人都有平等的机会,我如何在c#中做到这一点
本文关键字:机会 这一点 一种 方式 每个人 我想要 | 更新日期: 2023-09-27 17:50:24
我有一个函数,像这样,
private void Step()
{
foreach (A a in aList)
a.Act();
foreach (B b in bList)
b.Act();
foreach (C c in cList)
c.Act();
}
a获得第一个机会b获得第二个机会c获得最后一个机会,
我想要一种方法,让每个人都有平等的机会,我怎么在c#中做到这一点?
谢谢你的帮助!
我将定义一个接口IActable
(选择您的名字),它定义Act()
。
public interface IActable
{
void Act();
}
使A、B和C实现可执行性。然后,将函数更改为以下操作:
private void Step()
{
var all = new List<IActable>();
all.AddRange(aList);
all.AddRange(bList);
all.AddRange(cList);
all = all.Shuffle(new Random());
foreach (IActable a in all)
{
a.Act();
}
}
Shuffle方法,从这里偷来的
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random rng)
{
T[] elements = source.ToArray();
// Note i > 0 to avoid final pointless iteration
for (int i = elements.Length-1; i > 0; i--)
{
// Swap element "i" with a random earlier element it (or itself)
int swapIndex = rng.Next(i + 1);
T tmp = elements[i];
elements[i] = elements[swapIndex];
elements[swapIndex] = tmp;
}
// Lazily yield (avoiding aliasing issues etc)
foreach (T element in elements)
{
yield return element;
}
}
使用plinq的并行实现。(不保留顺序)
private void Step()
{
var all = new List<IActable>();
all.AddRange(aList);
all.AddRange(bList);
all.AddRange(cList);
all.AsParallel().ForAll(a=>a.Act());
}
ThreadPool。QueueUserWorkItem
文档页中的示例:
using System;
using System.Threading;
public class Example {
public static void Main() {
// Queue the task.
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc));
Console.WriteLine("Main thread does some work, then sleeps.");
// If you comment out the Sleep, the main thread exits, and
// therefore the application ends, before the work item
// runs on the thread pool thread. The thread pool uses background
// threads, which do not keep the application running. (This
// is a simple example of a race condition.)
Thread.Sleep(1000);
Console.WriteLine("Main thread exits.");
}
// This method performs the work. It will be invoked in a thread
// running in the .NET threadpool.
static void ThreadProc(Object stateInfo) {
// No state object was passed to QueueUserWorkItem, so
// stateInfo is null.
Console.WriteLine("Hello from the thread pool.");
}
}
在您的场景中,您可以简单地将来自各种列表的所有工作项排队。不能保证线程池的处理顺序。但是,如果要完成的工作相当"短"——也就是说,如果线程调度所需的时间与执行实际工作所需的时间"大致相同"——那么您可能希望对操作进行洗牌,以便在所有线程池线程之间提供更公平的机会。
如果您的操作运行时间较长——假设几十秒或更长——那么线程池将提供良好的公平性,并且假设线程之间没有争用,您可能不需要在对工作项进行排队之前对其进行洗刷。
您可以使用多个线程并行运行它们(Cheeso的答案)-注意,在这种情况下,绝对不能保证所有方法都将同时运行。在使用多线程方法之前,您应该定义"机会均等"的实际含义。
或者您需要决定您希望函数执行的顺序并进行适当的排序。即分配优先级,把所有的放在同一个列表中(参见Brook的回答),并按优先级排序。