首页 > 系统相关 >Powershell 并发任务 | Runspace 线程 | 结果获取

Powershell 并发任务 | Runspace 线程 | 结果获取

时间:2024-01-30 14:01:29浏览次数:20  
标签:脚本 Jobs Runspace Powershell 任务 线程 txt PowerShell

介绍

在 PowerShell 中进行多任务处理(Multithreading 或 Parallel Processing)主要目的是提高脚本的执行效率和性能。对于需要处理大量数据或执行多个独立任务的脚本来说尤其有用。

  1. 提高性能: 多任务处理允许脚本同时执行多个任务,从而加快整体执行速度。对于需要处理大型数据集或执行耗时的操作时尤为重要。

  2. 充分利用多核处理器: 现代计算机配备了多核处理器。通过多任务处理,充分发挥这些多核处理器的性能,提高整体计算能力。

  3. 并行执行独立任务: 在某些情况下,脚本需要执行多个相互独立的任务。多任务处理使得这些任务同时进行,而不是依次执行,提高脚本的效率。

  4. 提高响应性: 脚本需要响应用户输入或事件,多任务处理可以确保主线程(通常是用户界面线程)保持响应,而后台线程处理其他任务。

  5. 资源分配: 多任务处理允许更灵活地分配系统资源,例如内存、CPU 时间等,以满足不同任务的需求。

Runspace

在 PowerShell 中,使用 PowerShell Jobs、Runspace 等技术来实现多任务处理。 本文使用 Runspace,Runspace 是 PowerShell 中用于实现多任务处理的一种机制,其优势主要体现在以下几个方面:

  1. 轻量级: Runspace 是一种轻量级的线程池技术,相较于创建完整的 PowerShell 进程或 Runspace 进程,资源开销较小。在一个脚本中可以创建多个 Runspace,以执行并发任务而不过度消耗系统资源。

  2. 资源隔离: 每个 Runspace 拥有独立的 PowerShell 运行环境和内存空间,意味着一个 Runspace 的异常不会影响到其他 Runspace,提供了更好的资源隔离。

  3. 更好的性能: Runspace 可以同时执行多个任务,充分利用多核处理器和系统资源,从而提高整体脚本执行的性能。在需要处理大量数据或执行复杂任务时,Runspace 能够更高效地完成工作。

  4. 适用于并行处理: Runspace 是适用于并行处理的一种机制,可以同时执行多个任务,不是按顺序一个一个地执行。这对于需要并行处理独立任务的脚本非常有帮助。

  5. 异步执行: Runspace 可以用于实现异步执行任务,意味着脚本可以继续执行而无需等待所有任务完成。对于需要同时进行多个长时间运行的任务时尤为有用。

示例

# 开始时间
$StartTime = Get-Date
# 处理任务
$Worker = {
    param($Filename)
    Write-Host "Processing $filename"
    Start-Sleep -Seconds 1 # Doing some work....
    $Item = New-Item -Name $Filename
    Write-Output $Item.FullName
}
# 最大并发
$MaxRunspaces = 10

try {
	# 线程池
    $RunspacePool = [runspacefactory]::CreateRunspacePool(1, $MaxRunspaces)
    $RunspacePool.Open()

    $Jobs = New-Object System.Collections.ArrayList

    $Filenames = @("file1.txt", "file2.txt", "file3.txt", "file4.txt", "file5.txt", "file6.txt", "file7.txt", "file8.txt", "file9.txt", "file10.txt", "file11.txt")

    foreach ($File in $Filenames) {
        Write-Host "Creating runspace for $File"
        $PowerShell = [powershell]::Create()
        $PowerShell.RunspacePool = $RunspacePool
        $PowerShell.AddScript($Worker).AddArgument($File) | Out-Null
        
        $JobObj = New-Object -TypeName PSObject -Property @{
            Runspace   = $PowerShell.BeginInvoke()
            PowerShell = $PowerShell  
        }

        $Jobs.Add($JobObj) | Out-Null
    }

    while ($Jobs.Runspace.IsCompleted -contains $false) {
        Write-Host (Get-date).Tostring() "Still running..."
        Start-Sleep 1
    }
}
finally {
	# 始终关闭进程池
    $RunspacePool.Close()
}
# 结束时间
$endTime = Get-Date
# 运行时间
Write-Host "The script runs for Total time (s):$(($endTime - $StartTime).TotalSeconds)"
# 任务对象信息
$Jobs.powershell.Streams
$Jobs.powershell.haderrors

image.png image.png

逻辑介绍

代码逻辑的解释:

  1. 定义 Worker 脚本块:

    • $Worker 脚本块是一个用于处理文件的脚本块。接受一个文件名参数,输出处理后的结果。
  2. 设置并发 Runspaces 数量:

    • $MaxRunspaces 变量定义最大 Runspaces 数量,即同时处理的最大任务数。
  3. 创建 Runspace 池:

    • 使用 [runspacefactory]::CreateRunspacePool 创建 Runspace 池,设置最小和最大 Runspaces 数量,并打开池。
  4. 创建并发任务:

    • 使用 foreach 循环遍历文件名数组 $Filenames
    • 每个文件名创建一个 PowerShell 对象 $PowerShell
    • $Worker 脚本块添加到 PowerShell 中,并通过 AddArgument 传递文件名参数。
    • 使用 BeginInvoke 异步启动 PowerShell,返回一个 Runspace 对象。
    • 创建一个包含 Runspace 和 PowerShell 对象的自定义对象 $JobObj,并将其添加到 $Jobs 数组中。
  5. 等待任务完成:

    • 使用 while 循环检查所有任务是否完成。循环条件是检查 $Jobs.Runspace.IsCompleted 数组,确保所有任务都完成。
    • 在循环中使用 Start-Sleep 暂停一秒钟,以避免过于频繁的检查。
  6. 关闭 Runspace 池:

    • finally 块中关闭 Runspace 池,确保资源的正确释放。
  7. 输出结果和错误信息:

    • 输出所有任务的 Streams(输出、错误等)。
    • 输出是否有错误发生($Jobs.powershell.haderrors)。

这段代码通过并发处理多个文件,每个文件在一个独立的 Runspace 中执行,最终输出各任务的结果和错误信息。并发处理可以提高处理大量文件时的效率。

Ending


::: hljs-center

喜欢的话,请收藏+关注~ 万一有趣的事还在后头呢~

:::

标签:脚本,Jobs,Runspace,Powershell,任务,线程,txt,PowerShell
From: https://blog.51cto.com/xingjia/9483868

相关文章

  • Qt 线程同步 QMutex、QReadWriteLock、QWaitCondition
    在Qt中,线程同步可以使用以下几种方式来实现:一、互斥锁(QMutex)互斥锁用于保护共享资源,确保在同一时间只有一个线程能够访问该资源。线程在访问共享资源之前需要获取互斥锁,使用完后再释放互斥锁,以确保同一时间只有一个线程在执行关键代码段。1.创建QMutex对象:在需要进行线程同步的......
  • 一次因PageHelper引起的多线程复用问题的排查和解决 | 京东物流技术团队
    A、ProblemDescription1\.PageHelper方法使用了静态的ThreadLocal参数,在startPage()调用紧跟MyBatis查询方法后,才会自动清除ThreadLocal存储的对象。2\.当一个线程先执行了A方法的PageHelper.startPage(intpageNum,intpageSize)后,在未执行到SQL语句前,因为代码抛异常而提前结束......
  • 多线程之读者写者模型(三千字长文详解)
    多线程之读者写者模型什么是读者写者问题?为了能理解这个概念我们先举个列子:我们在小时候,通常有一个东西叫做——黑板报!在一个班级上,有一个叫小明的学生,他字写的很高,有一天他正在画黑板报,同学们在他旁边看,窃窃私语的猜他在画什么东西!有的猜说画的是蛇,有的说画的是龙,等等但是到......
  • 一次因PageHelper引起的多线程复用问题的排查和解决 | 京东物流技术团队
    A、ProblemDescription1.PageHelper方法使用了静态的ThreadLocal参数,在startPage()调用紧跟MyBatis查询方法后,才会自动清除ThreadLocal存储的对象。2.当一个线程先执行了A方法的PageHelper.startPage(intpageNum,intpageSize)后,在未执行到SQL语句前,因为代码抛异常而提前结束......
  • 深入浅出Java多线程(三):线程与线程组
    「引言」大家好,我是你们的老伙计秀才!今天带来的是[深入浅出Java多线程]系列的第三篇内容:线程与线程组。大家觉得有用请点赞,喜欢请关注!秀才在此谢过大家了!!!在现代软件开发中,多线程编程已成为提升程序性能和并发能力的关键技术之一。Java作为主流的面向对象编程语言,其对多线程的支......
  • 给线程起名
    //用API给线程起名1publicclassMyThreadApiextendsThread{2@Override3publicvoidrun(){4for(inti=0;i<5;i++){5System.out.println(Thread.currentThread()+"子线程:"+i);6}7}8}11......
  • hashmap线程不安全 ConcurrentHashMap是如何实现线程安全的
       2、JDK1.8中的数据覆盖(1)dk1.7的数据丢失、死循环问题在JDK1.8中已经得到了很好的解决,直接在HashMap的resize()中完成了数据迁移。(2)为什么说JDK1.8会出现数据覆盖的情况?查看这段JDK1.8中的put操作代码:在这里插入图片描述如下图框中的代码是判断是否出现hash碰撞,假设两个......
  • 线程的三种创建方式
    1//方式一:继承Thread类2publicclassThread{3publicstaticvoidmain(String[]args){4Threadt=newMyThread();5t.start();67for(inti=0;i<5;i++){8System.out.println("主线程:"+......
  • java用多线程批次查询大量数据(Callable返回数据)方式
    我看到有的数据库是一万条数据和八万条数据还有十几万条,几百万的数据,然后我就想拿这些数据测试一下,发现如果用java和数据库查询就连一万多条的数据查询出来就要10s左右,感觉太慢了。然后网上都说各种加索引,加索引貌似是有查询条件时在某个字段加索引比较快一些,但是毕竟是人家的库不......
  • 线程分批处理数据及MyBatis的批量插入
    文章目录一、背景二、代码实现:三、分页查询下游批次处理场景四、MyBatis的批量插入1、活动表简单表结构:2、业务层组装数据:一、背景数据量较多时,我们常常遇到需要分批处理的情况,比如上千上万数据需要需要操作数据库时(入库或者更新),我们想到分批处理,或者解析文件数据量较多,我......