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".
$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
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