gpt4 book ai didi

.net - 在Powershell中交互使用Mutexes(et al)

转载 作者:行者123 更新时间:2023-12-04 04:50:29 29 4
gpt4 key购买 nike

在调试使用信号量进行跨进程同步的应用程序时,我偶然发现了使用PowerShell代替“其他”进程的想法。在PowerShell中执行以下操作可以正常工作:

// In C# application:
var sem = new Semaphore(0, 1, "CrossProcSem");
sem.WaitOne();

# In PowerShell session:
[1] C:\Projects $ $sem = New-Object System.Threading.Semaphore(0, 1, "CrossProcSem")
[2] C:\Projects $ $sem.Release()

而且,我可以根据需要在同一个信号量实例上重复调用 WaitOne()Release()

但是,当我尝试对Mutex执行相同的操作时,PowerShell一直声称互斥体已被放弃:
[1] C:\Projects $ $mtx = New-Object System.Threading.Mutex($false, "CrossProcMtx")
[2] C:\Projects $ $mtx.WaitOne()
True
[3] C:\Projects $ $mtx.ReleaseMutex()
[4] C:\Projects $ $mtx.WaitOne()
Exception calling "WaitOne" with "0" argument(s): "The wait completed due to an abandoned mutex."
At line:1 char:13
+ $mtx.WaitOne <<<< ()
+ CategoryInfo : NotSpecified: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : DotNetMethodException

该错误似乎在我之前获得互斥体一次后调用 WaitOne()的任何时候发生,无论是先前的 WaitOne调用还是要求其最初在构造函数中拥有:
[5] C:\Projects $ $mtx2 = New-Object System.Threading.Mutex($true)
[6] C:\Projects $ $mtx2.WaitOne()
Exception calling "WaitOne" with "0" argument(s): "The wait completed due to an abandoned mutex."
At line:1 char:14
+ $mtx2.WaitOne <<<< ()
+ CategoryInfo : NotSpecified: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : DotNetMethodException

[7] C:\Projects $ $mtx3 = New-Object System.Threading.Mutex
[8] C:\Projects $ $mtx3.WaitOne()
True
[9] C:\Projects $ $mtx3.WaitOne()
Exception calling "WaitOne" with "0" argument(s): "The wait completed due to an abandoned mutex."
At line:1 char:14
+ $mtx3.WaitOne <<<< ()
+ CategoryInfo : NotSpecified: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : DotNetMethodException

是Powershell在后台执行一些奇怪的线程恶作剧,还是我完全忘记了Mutex的工作原理?

最佳答案

默认情况下,powershell v2.0(在控制台上,而不是在图形ISE上)使用MTA线程池。这意味着每个交互行都在不同的线程上执行:

PS> [threading.thread]::CurrentThread.ManagedThreadId
13
PS> [threading.thread]::CurrentThread.ManagedThreadId
10
PS> [threading.thread]::CurrentThread.ManagedThreadId
8
PS> [threading.thread]::CurrentThread.ManagedThreadId
4

但是,非交互式脚本将在单个线程下运行,也就是说,调用该命令以运行该脚本的线程:
PS> $script = {
>> [threading.thread]::CurrentThread.ManagedThreadId
>> [threading.thread]::CurrentThread.ManagedThreadId
>> [threading.thread]::CurrentThread.ManagedThreadId
>> [threading.thread]::CurrentThread.ManagedThreadId
>> }
>>
PS> & $script
16
16
16
16

如果要通过单个线程交互式运行powershell,请使用-STA开关启动shell。您可以以交互方式执行此操作:
PS> powershell -sta
Windows PowerShell
Copyright (C) 2009 Microsoft Corporation. All rights reserved.

PS> $host.runspace | select threadoptions, apartmentstate
ThreadOptions ApartmentState
------------- --------------
ReuseThread STA

如您所见,powershell将使用单线程单元来执行交互式命令。对于使用WPF或WinForms,或者要使用系统范围的互斥锁,通常这是理想的选择:
PS> $mtx = New-Object System.Threading.Mutex($false, "CrossProcMtx")
PS> $mtx.WaitOne()
True
PS> $mtx.ReleaseMutex()
PS> $mtx.WaitOne()
True

顺便说一句,powershell v3(与Windows 8一起发货,并且在Win 7上也可以使用较低版本)将-STA用作控制台的默认模式。图形Powershell ISE在v2和v3中始终使用-STA。

关于.net - 在Powershell中交互使用Mutexes(et al),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7664490/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com