解決策: SendAsync()
Send()
ドキュメントが主張するほど同期していないのは残念です。SendAsync()
代わりに非同期バリアントを使用し、SendCompleted
イベントを使用して同期性を提供することが最も有益であることがわかりました。この問題を解決するために私が書いた次の汎用関数を参照してください (ただし、さまざまな非同期呼び出しに使用できます)。
<#
.SYNOPSIS
Calls a script block and waits for the specified event.
.DESCRIPTION
Provides a convenient way to call an asynchronous method with synchronous semantics.
This is achieved by registering to receive an event before calling the block that is
expected to signal its completion via a .NET event. The given script block need not
necessarily cause the event to be signaled, but that is the most obvious use case.
.PARAMETER EventSource
The object expected to raise the event.
.PARAMETER EventName
The name of the expected event.
.PARAMETER ScriptBlock
This block will be executed after registering the event and before waiting for the event.
.PARAMETER Timeout
Maximum duration in seconds to wait for the expected event. Default value of -1 means
to wait indefinitely. No error is raised when this timeout is reached.
.NOTES
Author: Erik Elmore <erik@ironsavior.net>
#>
function Wait-AsyncCall {
Param(
[Parameter(Mandatory = $True, Position = 0)]
$EventSource,
[Parameter(Mandatory = $True, Position = 1)]
[string]$EventName,
[Parameter(Mandatory = $True, Position = 2)]
[ScriptBlock]$ScriptBlock,
[int]$Timeout = -1
)
$id = "Wait-AsyncCall:$($EventName):$([guid]::NewGuid().ToString())"
Register-ObjectEvent $EventSource $EventName -SourceIdentifier $id -EA Stop
try {
$output = &$ScriptBlock
Wait-Event -SourceIdentifier $id -Timeout $Timeout -EA SilentlyContinue |Remove-Event -EA SilentlyContinue
}
finally {
Unregister-Event -SourceIdentifier $id -EA SilentlyContinue
}
$output
}
を使用Wait-AsyncCall
すると、代わりにAsyncSend()
メソッドを使用できますが、同期セマンティクスを使用します。元のコード ブロックは次のようになります。
$msg = New-Object Net.Mail.MailMessage
foreach( $To in $Recipients ) {
$msg.To.Add($To)
}
$msg.From = $From
$msg.Subject = $Subject
$msg.Body = $Body
$ctype = New-Object Net.Mime.ContentType -Property @{
MediaType = [Net.Mime.MediaTypeNames+Application]::Octet
Name = $AttachmentName
}
$msg.Attachments.Add([Net.Mail.Attachment]::CreateAttachmentFromString($csv, $ctype))
$client = new-object System.Net.Mail.SmtpClient($SMTPServer)
Wait-AsyncCall $client "SendCompleted" { $client.SendAsync($msg, $Null) }