执行一段代码,一次性运行,而不会阻塞其他并行线程。

huangapple go评论65阅读模式
英文:

Execute a piece of code in one run without blocking it for other parallel threads

问题

以下是您要翻译的代码部分:

Let's say you have piece of code within a method, which doesn't use any critical resources, but you want to execute it in one run, because you want to make sure, that the code is executed as fast as possible without any pause due to scheduling.

If you would take `lock` or `SemaphoreSlim` like bellow, the code within them will be blocked for every other thread which would run parallel and that would have a negative impact on performance. Of course `SemaphoreSlim` offers the possibility to define the number of parallel threads, but I don't want to manage it by myself.

private readonly object myLock = new object();
lock (this.teamLock)
{
  // ... code
}
// 
private readonly SemaphoreSlim semaphore = new SemaphoreSlim(1, 1);

public async Task LockAsync(Func<Task> worker)
{
    await semaphore.WaitAsync();
    try
    {
        // ... code
    }
    finally
    {
        semaphore.Release();
    }
}

Is there another way to make sure that code is executed in one run?
英文:

Let's say you have piece of code within a method, which doesn't use any critical resources, but you want to execute it in one run, because you want to make sure, that the code is executed as fast as possible without any pause due to scheduling.

If you would take lock or SemaphoreSlim like bellow, the code within them will be blocked for every other thread which would run parallel and that would have a negative impact on performance. Of course SemaphoreSlim offers the possibility to define number of parallel threads, but I don't want to manage it by myself.

private readonly object myLock = new object();
lock (this.teamLock)
{
  // ... code
}
// 
private readonly SemaphoreSlim semaphore = new SemaphoreSlim(1, 1);

public async Task LockAsync(Func&lt;Task&gt; worker)
{
    await semaphore.WaitAsync();
    try
    {
        // ... code
    }
    finally
    {
        semaphore.Release();
    }
}

Is there another way to make sure, that a code is executed in one run?

答案1

得分: 2

.NET线程由操作系统线程支持,这些线程使用抢占式调度(而您正在询问如何防止抢占)。您可以通过挂起其他线程来防止它们在同一应用程序中运行。为了枚举和挂起它们,您需要降级到Win32级别。然而,如果您想运行托管代码,这可能会导致死锁,因为运行时通常假定其线程正在运行。还有来自其他应用程序的所有其他线程。

另外,如果您在Windows上,您可以将您的线程优先级提升到实时级别以避免其他线程获得动态优先级提升到与您的线程相同的级别。但一般情况下不建议这样做,特别是对于托管代码,出现死锁的原因与上面的情况相同。除非您非常小心,否则缺乏动态提升可能会导致死锁。使用实时优先级需要完全了解所有依赖关系以及它们与实时优先级线程的交互方式。

因此,尽管从技术上讲这是可能的,但这需要相当多的工作,而且实际上不应该使用托管代码,因为运行时并不是为此设计的。您应该将其重写为非托管代码,然后在单独的实时进程中运行它。然后验证您的依赖关系是否按预期工作。

您希望一次运行它,因为您希望确保代码尽快执行,而不会因调度而暂停。

实际上,您可能应该降低优先级,或者只保留默认设置。动态优先级提升将自动执行对用户最有利的操作。如果有一个需要占用大量时间的CPU绑定方法,考虑降低优先级。

英文:

TL;DR: you probably don't want to do it, and even if you do it's probably not woth it.

.NET threads are backed by OS threads, which use preemptive scheduling (and what you're asking is how to prevent preemption).

You can prevent other threads from running in the same app by suspending them. You'd need to drop down to the Win32 level in order to enumerate and suspend them. This can cause deadlocks if you want to run managed code, though, since the runtime in general assumes its threads are running. And there's still all the other threads from other apps.

Alternatively, if you're on Windows, you can raise your thread priority above the realtime level to avoid other threads getting dynamic priority boosts up to the same level as your thread. This is not recommended in general, though, and that goes double for managed code, for the same reasons as the deadlock above. The lack of dynamic boosting can cause deadlocks unless you are very careful. Use of realtime priorities require a complete understanding of all your dependencies and how they interact with a realtime priority thread.

So, while it's technically possible, it's quite a bit of work; and it really should not be managed code at all, since the runtime isn't designed for this. You would rewrite it as unmanaged code and then run it in a separate realtime process. And then verify that your dependencies will work as expected.

> you want to execute it in one run, because you want to make sure, that the code is executed as fast as possible without any pause due to scheduling.

Actually, what you should probably do is lower the priority, or just leave it the default. Dynamic priority boosts will automatically do what's best for the user. If anything, if you have a CPU-bound method that takes a noticeable amount of time, consider lowering the priority.

huangapple
  • 本文由 发表于 2023年4月11日 00:38:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/75978905.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定