【问题标题】:C# thread scheduling with deadline带有截止日期的 C# 线程调度
【发布时间】:2019-10-07 21:40:09
【问题描述】:

我目前正在尝试用 C# 实现一个实时多线程软件。我需要3个线程。每个线程执行都必须在截止日期(500µs / 100µs / 50µs)之前完成。线程必须在整个运行时并行运行(直到用户关闭程序)。

有没有一种机制可以保证线程执行不会超过deadline?

这是我的代码:

static void Main(string[] args)
{
    Thread thread1 = new Thread(FirstThread);
    Thread thread2 = new Thread(SecondThread);
    Thread thread3 = new Thread(ThirdThread);

    thread1.start();
    thread2.start();
    thread3.start();
}

static void FirstThread()
{
    while(true)
    {
        SleepMicroSec(500);
    }
}

static void SecondThread()
{
    while(true)
    {
        SleepMicroSec(100);
    }
}

static void ThirdThread()
{
    while(true)
    {
        SleepMicroSec(50);
    }
}

private static void SleepMicroSec(long microSec)
{
    var sw = Stopwatch.StartNew();

    while (sw.ElapsedTicks / (Stopwatch.Frequency / (1000L * 1000L)) < microSec)
    {

    }
}

如果达到任务期限,我希望调度程序能够执行上下文切换。

提前感谢您的回答!

【问题讨论】:

  • 澄清一下,如果没有达到deadline,你要取消任务吗?
  • “保证”的唯一方法是在每个线程达到其限制并且仍在运行时中止它。在很多情况下,这可能是不可取的......
  • 我不想取消任务,只想切换上下文运行另一个任务
  • @bgabriel I don't want to cancel the task, I just want to switch the context to run another task. 因此,如果任务 A 仍在运行并且是时候启动任务 B,您不想中止或终止任务 A,而是要启动任务 B,同时运行两个任务A 和 B 同时?
  • @Patrick Tucci 任务应该一个接一个地执行。唯一重要的是它们的执行时间不会超过截止日期

标签: c# multithreading scheduled-tasks multitasking


【解决方案1】:

这是一个在后台线程中重复调用操作的方法,每次超过最后期限时中止并重新启动线程。它还接受CancellationToken 以允许过早取消程序(在程序结束之前)。

private static void RepeatInBackgroundThread(Action action, int timeout,
    CancellationToken cancellationToken)
{
    var timer = new System.Timers.Timer(timeout);
    timer.AutoReset = false; // to raise the Elapsed event only once
    var thread = new Thread(() =>
    {
        while (true)
        {
            if (cancellationToken.IsCancellationRequested) return;
            timer.Start();
            action();
            timer.Stop();
        }
    });
    timer.Elapsed += (sender, e) =>
    {
        thread.Abort();
        thread.Join(); // Wait for the thread to die
        if (cancellationToken.IsCancellationRequested) return;
        RepeatInBackgroundThread(action, timeout, cancellationToken);
    };
    thread.IsBackground = true;
    thread.Start();
}

使用示例:

var random = new ThreadLocal<Random>(() => new Random());
var cts = new CancellationTokenSource();
RepeatInBackgroundThread(() => Thread.Sleep(random.Value.Next(0, 1000)), 500, cts.Token);
RepeatInBackgroundThread(() => Thread.Sleep(random.Value.Next(0, 200)), 100, cts.Token);
RepeatInBackgroundThread(() => Thread.Sleep(random.Value.Next(0, 100)), 50, cts.Token);
//cts.CancelAfter(10000);

需要注意的是aborting threads is not a good practice一般。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-16
    • 2018-03-25
    • 1970-01-01
    • 2023-03-24
    • 2013-06-24
    • 2019-10-14
    相关资源
    最近更新 更多