寂寞的领带 · 上海市人民政府办公厅印发《关于新时期强化投资 ...· 3 月前 · |
痴情的香菜 · E周新势力|小鹏G3 ...· 1 年前 · |
爱运动的乌龙茶 · 坦克500 Hi4-T正式预售 坦克_懂车帝· 1 年前 · |
会开车的钱包 · 倒霉蛋大战气运王漫画|官方在线漫画全集-快看· 1 年前 · |
高大的红薯 · 我的夫君是冥王漫画|官方在线漫画全集-快看· 1 年前 · |
我需要将一个C#应用程序移植到Powershell。应用程序使用线程进行繁重的工作,我需要尽可能地将应用程序的端口保持在与原始C#应用程序接近的位置。问题是,我不能使用 System.Threading.Thread 生成新线程,因为 System.Threading.ThreadStart 在Powershell中请求 2 参数,而C#代码只在代码中请求 1 ,因为它是委托。
下面是C#中生成线程的最小类示例
using System;
using System.Threading;
namespace ThreadingTest
class ThreadingTest
public delegate void UpdateElementCallback(string message);
public ThreadingTest() {
Console.WriteLine("Hello from Thread " + Thread.CurrentThread.ManagedThreadId);
Thread newThread = new Thread(new ThreadStart(MethodToBeCalledFromAnotherThread));
newThread.Start();
private void UpdateElement(string message) {
Console.WriteLine(message + Thread.CurrentThread.ManagedThreadId);
private void MethodToBeCalledFromAnotherThread() {
UpdateElement("Hello from Thread ");
}
在运行的示例中输出。
Hello from Thread 1
Hello from Thread 4
下面是我尝试过的一个非工作端口到Powershell代码。
Add-Type -AssemblyName System
Add-Type -AssemblyName System.Threading
class ThreadingTest {
[Action[String]]$UpdateElementCallback =
param([String]$message)
$callBackThread = [System.Threading.Thread]::CurrentThread.ManagedThreadId
"$message $callBackThread" | Out-Host
# Constructor
ThreadingTest() {
# Get current thread id
$currentThread = [System.Threading.Thread]::CurrentThread.ManagedThreadId
# Print current thread id
"Hello from Thread $currentThread" | Out-Host
# Create a new thread (This line fails)
$newThread = [System.Threading.Thread]::new([System.Threading.ThreadStart]::new($this.UpdateElementCallback))
$newThread.Start
$ThreadingTestObject = [ThreadingTest]::new()
在运行的示例中输出。
Hello from Thread 21
MethodException: .../ThreadingTest.ps1:21:9
Line |
21 | $newThread = [System.Threading.Thread]::new([System.Threading …
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Cannot find an overload for "new" and the argument count: "1".
创建新 ThreadingStart 对象的Powershell调用具有以下签名
System.Threading.ThreadStart new(System.Object object, System.IntPtr method)
作为参数,我必须传递什么来使它工作? System.Object 必须是什么,作为参数传递的 System.IntPtr 必须是什么才能工作?
我想做一个注意,我需要保持代码尽可能接近原。我试过开始-工作和运行空间。运行空间有效,但它需要大量的样板。我想知道是否有一种通过使用 System.Threading.Thread 使其工作的方法
发布于 2020-06-06 23:30:35
找到的解决方法是使用C#在那里创建一个C#对象并将其传递给Powershell。然后将Powershell中的线程对象作为常规使用。
从Powershell调用C#并使用System.Threading.Thread
Notes :此代码仅适用于 Powershell 7 。以前的版本抛出一个错误,无法将类中的方法转换为Action。
$code = @"
using System;
using System.Threading;
namespace ThreadingTest
public class ThreadCreator
public Thread CreateAThread(ThreadStart threadStart) {
return new Thread(threadStart);
public ThreadStart CreateAThreadStart(Action threadStart) {
return new ThreadStart(threadStart);
Add-Type -TypeDefinition $code -Language CSharp
class ThreadingTestClass {
$ThreadCreator
[System.Threading.Thread] $NewThread
[bool] $finishCountingThread = $false
[int] $ClassThreadId
# Constructor
ThreadingTestClass() {
# Get the current thread id
$this.ClassThreadId = [System.Threading.Thread]::CurrentThread.ManagedThreadId
# Print current thread id
Write-Host "Hello from " -NoNewline
Write-Host "Thread $($this.ClassThreadId)" -ForegroundColor Green
# Create a ThreadCreator object
$this.ThreadCreator = Invoke-Expression "[ThreadingTest.ThreadCreator]::new()"
# Get a [System.Threading.Thread] object from the C# code to run '[Void] MethodToBeCalledFromAnotherThread()' in another thread
$this.NewThread = $this.ThreadCreator.CreateAThread($this.ThreadCreator.CreateAThreadStart($this.MethodToBeCalledFromAnotherThread))
# Start the thread
$this.NewThread.Start()
# Wait for user to press Escape. This 'do until' is executed while the other thread is running in the background. It doesn't wait for $this.NewThread to finish
$keyPressed = [System.Console]::ReadKey().Key
} until ($keyPressed -eq [System.ConsoleKey]::Escape)
# Set the $finishCountingThread variable to stop counting
$this.finishCountingThread = $true;
# Wait for the thread to finish gracefully before ending
$this.NewThread.Join()
[Void] MethodToBeCalledFromAnotherThread() {
# Get the current thread id
$currentThreadID = [System.Threading.Thread]::CurrentThread.ManagedThreadId
# Say hello from the thread this method is running on
Write-Host "Hello from " -NoNewline
Write-Host "Thread $currentThreadId" -ForegroundColor Blue
# Count from 0 to 10000
for ($i = 0; $i -le 10000; $i++) {
# Check boolean to know whether to finish counting or not
if($this.finishCountingThread) {
Write-Host "`nFinishing spawned " -NoNewline
Write-Host "Thread $currentThreadID..." -ForegroundColor Blue
break
# Print on the console the current value of $i
Write-Host "`rPress ESC to stop spawned " -NoNewline
Write-Host "Thread $currentThreadID " -NoNewline -ForegroundColor Blue
Write-Host "and quit program: " -NoNewline
Write-Host "[Counting $i in Thread $currentThreadID] " –NoNewline -ForegroundColor Blue
Write-Host "Keys are being listened to on " -NoNewline
Write-Host "Thread $($this.ClassThreadId)" -NoNewline -ForegroundColor Green
# Check if the counting finished before the user pressed Escape
if (-Not $this.finishCountingThread) {
"`nCounting finished" | Out-Host
"Press ESC to quit program..." | Out-Host
# Set cursor visible to false to see colors without a jittering cursor
[System.Console]::CursorVisible = $false
"`n`n" | Out-Host
$ThreadingTestClassObject = [ThreadingTestClass]::new()
"`n`n" | Out-Host
代码调用C#代码来创建具有创建线程的方法的对象。其中两个方法被调用以创建 System.Threading.Thread对象 并返回它。然后线程对象可以从Powershell中使用。因为传递给生成的线程( MethodToBeCalledFromAnotherThread )的方法在Powershell类中,所以即使它在另一个线程中,也可以访问该类的属性。
当它运行到结束时输出:
当按下 ESC 以停止计数时输出
替代-使用System.ComponentModel.BackgroundWorker
下面没有回答如何在Powershell中使用 System.Threading.Thread 的问题,但它是另一种不调用任何C#代码、不使用运行空间或乔布斯的多线程解决方案。它使用BackgroundWorker,如下所示。当使用表单或WPF GUI时,它非常有用。输出与其他代码中的输出相同。
Notes :此代码仅适用于 Powershell 7 。以前的版本抛出一个错误,无法将类中的方法转换为Action。
class ThreadingTestClass {
[System.ComponentModel.BackgroundWorker] $BackgroundWorker
[bool] $finishCountingThread = $false
[int] $ClassThreadId
# Constructor
ThreadingTestClass() {
# Get the current thread id
$this.ClassThreadId = [System.Threading.Thread]::CurrentThread.ManagedThreadId
# Print current thread id
Write-Host "Hello from " -NoNewline
Write-Host "Thread $($this.ClassThreadId)" -ForegroundColor Green
# Create a BackgroundWorker object, set the event and set it to support cancellation
$this.BackgroundWorker = [System.ComponentModel.BackgroundWorker]::new()
$this.BackgroundWorker.add_DoWork($this.MethodToBeCalledFromAnotherThread)
$this.BackgroundWorker.WorkerSupportsCancellation = $true
# Run the method 'MethodToBeCalledFromAnotherThread' in another thread
$this.BackgroundWorker.RunWorkerAsync()
# Wait for user to press Escape. This 'do until' is executed while the other thread is running in the background. It doesn't wait for $this.BackgroundWorker to finish
$keyPressed = [System.Console]::ReadKey().Key
} until ($keyPressed -eq [System.ConsoleKey]::Escape)
# Set the $finishCountingThread variable to stop counting
$this.finishCountingThread = $true
if ($this.BackgroundWorker.WorkerSupportsCancellation -and $this.BackgroundWorker.IsBusy) {
# Cancel the background worker work
$this.BackgroundWorker.CancelAsync()
# while loop only needed if there is no GUI or anything else preventing PS from continuing and trying to exit
while ($this.BackgroundWorker.IsBusy) {
# Do nothing. Block calling thread and wait for the Background worker to finish cancelling
# Otherwise, Powershell will continue to execute code further and it can
# end code execution while there is another thread in the background
# That will cause an exception and a crash
# GUIs usually prevent PowerShell from exiting
# for which this may not be needed in a Form or WPF application
[Void] MethodToBeCalledFromAnotherThread([Object]$sender, [System.ComponentModel.DoWorkEventArgs]$e) {
# Get the current thread id
$currentThreadID = [System.Threading.Thread]::CurrentThread.ManagedThreadId
# Say hello from the thread this method is running on
Write-Host "Hello from " -NoNewline
Write-Host "Thread $currentThreadId" -ForegroundColor Blue
# Count from 0 to 10000
for ($i = 0; $i -le 10000; $i++) {
# Check boolean to know whether to finish counting or not
if($this.finishCountingThread) {
Write-Host "`nFinishing spawned " -NoNewline
Write-Host "Thread $currentThreadID..." -ForegroundColor Blue
break
# Print on the console the current value of $i
Write-Host "`rPress ESC to stop spawned " -NoNewline
Write-Host "Thread $currentThreadID " -NoNewline -ForegroundColor Blue
Write-Host "and quit program: " -NoNewline
Write-Host "[Counting $i in Thread $currentThreadID] " –NoNewline -ForegroundColor Blue
Write-Host "Keys are being listened to on " -NoNewline
Write-Host "Thread $($this.ClassThreadId)" -NoNewline -ForegroundColor Green
# Check if the counting finished before the user pressed Escape
if (-Not $this.finishCountingThread) {
"`nCounting finished" | Out-Host
"Press ESC to quit program..." | Out-Host
爱运动的乌龙茶 · 坦克500 Hi4-T正式预售 坦克_懂车帝 1 年前 |
会开车的钱包 · 倒霉蛋大战气运王漫画|官方在线漫画全集-快看 1 年前 |
高大的红薯 · 我的夫君是冥王漫画|官方在线漫画全集-快看 1 年前 |