Powershell线程处理问题

发布于 2024-12-03 17:10:39 字数 1223 浏览 0 评论 0 原文

我遇到了 powershell 问题,也许有人可以帮助我。我正在使用 powershell 2.0,我想创建和使用线程。我知道我可以使用工作,但这不是我想要的。 我想要一个脚本,它创建 Windows 窗体,并运行后台线程。由于表单需要 STA,所以这并不容易。运行“powershell.exe -sta”不是解决方案。

下面是我编写的脚本,用于简单的线程处理。但这不起作用。即使新线程也不会被创建。有什么建议吗,有什么问题吗?如果可以的话请帮助我!

问候,彼得。

function ThreadProc() {
    for ($i = 0; $i -lt 10; $i++) {
        $ApartmentState = [System.Threading.Thread]::CurrentThread.GetApartmentState()
        Write-Host "ThreadProc ($ApartmentState): $i"
        # Yield the rest of the time slice.
        [System.Threading.Thread]::Sleep(0)
    }
}

$ApartmentState = [System.Threading.Thread]::CurrentThread.GetApartmentState()
Write-Host "Main thread ($ApartmentState): Start a second thread."

$thread_job = New-Object System.Threading.ThreadStart(ThreadProc)
$thread = New-Object System.Threading.Thread($thread_job)
$thread.CurrentThread.SetApartmentState([System.Threading.ApartmentState]::STA)
$thread.Start()

for ($i = 0; $i -lt 4; $i++) {
    Write-Host("Main thread: Do some work.")
    [System.Threading.Thread]::Sleep(0)
}

Write-Host("Main thread: Call Join(), to wait until ThreadProc ends.")
$thread.Join()
Write-Host("Main thread: ThreadProc.Join has returned. Program end.")

I have a powershell problem, and maybe someone can help me. I'm using powershell 2.0, and i want to create, and use threads. I know that i can use jobs, but that is not what i want.
I want a script, that creates windows forms, and runs background threads too. Since forms needs STA, this is not easy. Running "powershell.exe -sta" is not a solution.

Below is my script that I wrote, for simple thread handling. But it doesn't work. Even the new thread wont be created. Any suggestion, what is wrong? Please help me if you can!

Regards, Peter.

function ThreadProc() {
    for ($i = 0; $i -lt 10; $i++) {
        $ApartmentState = [System.Threading.Thread]::CurrentThread.GetApartmentState()
        Write-Host "ThreadProc ($ApartmentState): $i"
        # Yield the rest of the time slice.
        [System.Threading.Thread]::Sleep(0)
    }
}

$ApartmentState = [System.Threading.Thread]::CurrentThread.GetApartmentState()
Write-Host "Main thread ($ApartmentState): Start a second thread."

$thread_job = New-Object System.Threading.ThreadStart(ThreadProc)
$thread = New-Object System.Threading.Thread($thread_job)
$thread.CurrentThread.SetApartmentState([System.Threading.ApartmentState]::STA)
$thread.Start()

for ($i = 0; $i -lt 4; $i++) {
    Write-Host("Main thread: Do some work.")
    [System.Threading.Thread]::Sleep(0)
}

Write-Host("Main thread: Call Join(), to wait until ThreadProc ends.")
$thread.Join()
Write-Host("Main thread: ThreadProc.Join has returned. Program end.")

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

虚拟世界 2024-12-10 17:10:39

注意到您的脚本中存在一些错误。首先 $thread_job,尝试这样做:

[System.Threading.ThreadStart]$thread_job = {ThreadProc};

您需要将 ThreadProc 放在括号中,否则它将被计算而不是作为函数传递。其次,您只需指定 ThreadStart 等委托的类型,PowerShell 就会为您转换内容;不需要新对象。

其次 CurrentThread 是一个静态成员 - 我猜 $thread.CurrentThread 是一个拼写错误,你的意思是:

$thread.SetApartmentState([System.Threading.ApartmentState]::STA);

我想你在让它工作时仍然会遇到问题 - 每当我尝试在 PowerShell 中使用线程之前我总是发生了严重的崩溃,没有真正的解释...

您可以用 C# 编写一个 cmdlet 并调用它吗?这样可能更容易做事 - 您可以设置一个新的运行空间并在另一个运行空间的线程中运行命令。

编辑

找到这些可能对您有帮助的链接:

http://weblogs.asp.net/adweigert/archive/2008/04/29/powershell-threading-for-powershell-v1-0.aspx
http://blogs.msdn.com/b/powershell/archive/2007/03/23/thread-apartmentstate-and-powershell-execution-thread.aspx

Noticed a couple of mistakes in your script. Firstly $thread_job, try this instead:

[System.Threading.ThreadStart]$thread_job = {ThreadProc};

You need to put the brackets around ThreadProc or it will be evaluated rather than passed as a function. Secondly you can just specify the type for delegates like ThreadStart and PowerShell will convert things for you; no need for New-Object.

Secondly CurrentThread is a static member - I'm guessing $thread.CurrentThread is a typo and you meant:

$thread.SetApartmentState([System.Threading.ApartmentState]::STA);

I imagine you'll still have problems getting it to work though - whenever I've tried using threads in PowerShell before I've always had nasty crashes with no real explanation...

Can you write a cmdlet in C# and call into that instead? Might be easier to do things that way - you could setup a new Runspace and run your command in the other Runspace's thread.

EDIT

Found these links that might help you:

http://weblogs.asp.net/adweigert/archive/2008/04/29/powershell-threading-for-powershell-v1-0.aspx
http://blogs.msdn.com/b/powershell/archive/2007/03/23/thread-apartmentstate-and-powershell-execution-thread.aspx

痴梦一场 2024-12-10 17:10:39

我认为您的问题接近于名为 Powershell 和后台工作人员的帖子。后台工作人员用于在后台线程。

尽管 Powershell 工作在 .NET 之上,但并不产生中间语言 (IL)。它是一种解释性语言,其代码不能在外部运行
powershell 运行空间的上下文。您也许可以使用您的代码创建我们自己的 PowerShell 运行空间并在那里运行您的脚本,然后编组
结果返回到您的主要会话。

I think that your question is somewhere close to a post called Powershell and Backgroundworker.Background worker is for running .NET code on a background thread.

Powershell, though is working on the top of .NET doesn't produce intermediate language (IL). Its an interpreted language and its code cannot run outside of the
context of a powershell runspace. you perhaps can use your code creating our own PowerShell Runspace and running your script there, and marshall the
results back to your primary session.

如痴如狂 2024-12-10 17:10:39

这是在 System.Threading.Thread 中播放 ScriptBlock 的有效解决方案。您还可以在 Thread.Start(args[]) 中传递参数并将 param(parameters[]) 添加到 ScriptBlock。在 PowerShell 中还有许多其他方法来获取独立线程,但这是我发现使用原始 [System.Threading.Thread] 的方法;

$mainthread = [System.Threading.Thread]::CurrentThread | Out-String;
[Console]::Write($mainthread);

[ScriptBlock] $scr = {
[System.Threading.Thread]::Sleep(4000);
$secondthread = [System.Threading.Thread]::CurrentThread | Out-String;
[Console]::Write($secondthread);
}
$ts = New-Object System.Threading.ParameterizedThreadStart($scr, $scr.GetType().GetMethod("Invoke").MethodHandle.GetFunctionPointer());
$newthread = [System.Threading.Thread]::new($ts);
$newthread.Start();
[System.Threading.Thread]::Sleep(500);
Write-Host 1;
[System.Threading.Thread]::Sleep(500);
Write-Host 2;
[System.Threading.Thread]::Sleep(500);
Write-Host 3;
[System.Threading.Thread]::Sleep(500);
Write-Host 4;
Read-Host;

This is a working solution to plays a ScriptBlock in a System.Threading.Thread. You can also pass arguments in Thread.Start(args[]) and add param(parameters[]) to ScriptBlock. There is many other ways to get independent threads in PowerShell, but this is the way I have founded to use original [System.Threading.Thread];

$mainthread = [System.Threading.Thread]::CurrentThread | Out-String;
[Console]::Write($mainthread);

[ScriptBlock] $scr = {
[System.Threading.Thread]::Sleep(4000);
$secondthread = [System.Threading.Thread]::CurrentThread | Out-String;
[Console]::Write($secondthread);
}
$ts = New-Object System.Threading.ParameterizedThreadStart($scr, $scr.GetType().GetMethod("Invoke").MethodHandle.GetFunctionPointer());
$newthread = [System.Threading.Thread]::new($ts);
$newthread.Start();
[System.Threading.Thread]::Sleep(500);
Write-Host 1;
[System.Threading.Thread]::Sleep(500);
Write-Host 2;
[System.Threading.Thread]::Sleep(500);
Write-Host 3;
[System.Threading.Thread]::Sleep(500);
Write-Host 4;
Read-Host;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文