- Tdnr_Sym
- ぬし
- 会議室デビュー日: 2005/09/13
- 投稿数: 464
- お住まい・勤務地: 明石・神戸
|
投稿日時: 2005-10-20 00:38
こんばんは。
| 引用: |
|
ジブさんの書き込み (2005-10-19 23:41) より:
メソッドの場合はInvokeなど、Windows的に明確にインタフェースを指定された呼び出しをする必要がある。
データの場合のマーシャリングの場合は一般的にシリアライズという表現を使う。
マーシャリングというのは、スレッド境界を越えるための必要要件で
InvokeやSeliarizeというのはそのための手段だと私は解釈しましたが、いかがなものでしょうか?
|
あれ!?なんだかあらぬ方向に理解が進んでいるように思うのですが…
いろんな分野の用語がまじりあってしまっているようですので、
まず、予備知識として以下のことを理解するのがよいのではないでしょうか。
・シリアライズ(serialize)
「ストリーム」や「オブジェクトの永続化」について
・マーシャリング(marshaling, marshalling)
「リモート処理」や「アプリケーションドメイン」について
・スレッド(thread)
Windowsにおける「スレッド」と「プロセス」の違いについて
・Invokeメソッド
WindowsのAPIレベルの基礎知識
「Windowメッセージ」と「メッセージキュー」と「メッセージループ」について
メッセージキューへ「メッセージ送信」するための関数
SendMessage関数…同期メッセージ送信
PostMessage関数…非同期メッセージ送信
どうでしょうか。
[ メッセージ編集済み 編集者: Tdnr_Sym 編集日時 2005-10-20 00:44 ]
|
- ジブ
- 大ベテラン
- 会議室デビュー日: 2005/09/22
- 投稿数: 135
|
投稿日時: 2005-10-20 00:47
Tdnr_Symさん、ありがとうございます。
| 引用: |
|
あれ!?なんだかあらぬ方向に理解が進んでいるように思うのですが…
いろんな分野の用語がまじりあってしまっているようですので、
まず、予備知識として以下のことを理解するのがよいのではないでしょうか。
|
相当、頓珍漢な発言だったようですね。失礼いたしました。
|
- 未記入
- ぬし
- 会議室デビュー日: 2004/09/17
- 投稿数: 667
|
投稿日時: 2005-10-20 01:39
| 引用: |
| ・シリアライズ(serialize)
「ストリーム」や「オブジェクトの永続化」について
|
他にも、シリアライズは(並列実行せずに)逐次実行させる場面でも使われる用語ですね。 一般的な FIFO キューに突っ込む行為もシリアライズと呼ぶことができます。データベースの分離レベルでも排他・逐次実行するレベルをシリアライズと呼びますね。
このスレで 渋木宏明(ひどり)さんが言っているシリアライズも、キュー整列・逐次実行のことを指していると思います。で、この整列行為をマーシャリングと呼んでも間違いとまでは言えないと思いますが、誤解されやすいのも事実でしょう。
|
- kanai
- ベテラン
- 会議室デビュー日: 2004/09/13
- 投稿数: 98
|
投稿日時: 2005-10-20 12:24
皆様、ご回答いただきありがとうございます。
「マーシャリング」については、ここでは「スレッドの同期」と書いたほうが誤解がなかったかも
しれません。
(が、MSDNでも普通に「マーシャリング」と書かれていたので…ご容赦ください)
少し前の書き込みへのレスになってしまいましたが、
| 引用: |
|
Tdnr_Symさんの書き込み(2005-10-15 11:12 )より:
そもそも同一プロセスのスレッド間で「マーシャリング」する必要はあるのでしょうか?
なんの目的で「マーシャリング」が必要なのでしょうか?
ご提示されたサンプルコードを拝見してもマーシャリングしているところが見当たらないのですが…
|
.NETマルチスレッドプログラミング 2:非同期デリゲートとスレッドプール
「別スレッドからフォーム、コントロールを扱う」
に書かれている通り、「コントロールのメソッド、プロパティはその作成スレッド以外からは呼び出してはいけない」
という事情により、このような「マーシャリング(UIスレッドへの同期)」は必要と考えています。
サンプルコードでは、以下の部分です。
| コード: |
|
Private Sub ReportProgress(ByVal message As String)
'SynchronizingObjectが設定されていればInvoke、そうでなければ普通に実行
If Not _SynchronizingObject Is Nothing Then
_SynchronizingObject.Invoke( _
New OnProgressDelegate(AddressOf OnProgress), _
New Object() {message})
Else
OnProgress(message)
End If
End Sub
|
|
- 渋木宏明(ひどり)
- ぬし
- 会議室デビュー日: 2004/01/14
- 投稿数: 1155
- お住まい・勤務地: 東京
|
投稿日時: 2005-10-20 13:19
| 引用: |
|
(が、MSDNでも普通に「マーシャリング」と書かれていたので…ご容赦ください)
|
MSDN 日本語版の表現が不適切なようですね。
直接原文を確認していませんが、いくつか切り出された箇所の原文を見る限り、限りなく誤訳に近いと思います>この場合のマーシャリング
ヘルプの原文は英文であり、日本語ヘルプとして提供されているコンテンツは「その手」の技術に精通した技術者が訳したものではありませんから、細かく見ていくと原文と微妙に食い違っていることもあります。
# と言っても10年近く前の状況と比べれば格段に品質は向上していますが。
|
- Tdnr_Sym
- ぬし
- 会議室デビュー日: 2005/09/13
- 投稿数: 464
- お住まい・勤務地: 明石・神戸
|
投稿日時: 2005-10-20 15:07
こんにちは。
まず、あまりMSDN日本語版の一部で使われている「マーシャリング」に、
惑わされないほうがよいと思います。
"marshal..." -> "マーシャリングする"という、すこし安直な訳し方がされているようなので。
.NET系の参考書で「マーシャリング」について、書かれているものがあればそれをご覧ください。きっと、「リモート処理」の章に分類されていると思います。「スレッド・同期処理」の章にはないと思います。
#私の持っている参考書でいえば
Jesse Liberty 著「プログラミングC# 開発運用 第3版」
つぎに、UIスレッドについてですが、
UIスレッドは、メイン処理としてメッセージループがあり、そこから各コントロール(ウィンドウ)へ
メッセージがディスパッチ(振り分け)されることで成り立っています。
#.NET Frameworkからは見えないですが、Windows APIレベルで理解されていれば分かることですね。
なので、別スレッドからはUIスレッドにメッセージを送信することで、UIスレッド側の処理を呼び出すことができます。
そのためにWindows APIでは、SendMessageやPostMessageといった関数を使用することができましたが、.NETにおいては、その代替としてInvokeメソッドなどを使うことになります。
#間違いがあれば、ご指摘お願いします。
#参考書のリンク追加
[ メッセージ編集済み 編集者: Tdnr_Sym 編集日時 2005-10-20 16:01 ]
|
- れい
- ぬし
- 会議室デビュー日: 2005/11/01
- 投稿数: 346
|
投稿日時: 2005-11-01 05:49
話が元にもどって失礼ですが、
最初の話題、SynchronizingObjectの使い方の件。
.Netの作法に従うというのであれば、
下記のように修正すればより礼儀正しく、パフォーマンスもよいかとおもいます。
1 OnProgressで他スレッドの場合でもInvokeできるようにする
2 OnProgressDelegateを定義しない。ReportProgressを定義しない。
3 InvokeRequiredをチェックする
Progressイベントのデリゲートが、ProgressEventという名前で
自動で定義されるというのが重要です。
| コード: |
|
Public Class Class1
'スレッドオブジェクト
Private _SubThread As Threading.Thread
'マーシャリング用オブジェクト
Private _SynchronizingObject As System.ComponentModel.ISynchronizeInvoke
Public Property SynchronizingObject() As System.ComponentModel.ISynchronizeInvoke
Get
Return _SynchronizingObject
End Get
Set(ByVal Value As System.ComponentModel.ISynchronizeInvoke)
_SynchronizingObject = Value
End Set
End Property
'別スレッドの処理を開始する
Public Sub Start()
'メインスレッドに名前を付ける
Threading.Thread.CurrentThread.Name = "メインスレッド"
'別スレッドを開始する
_SubThread = New Threading.Thread( _
New Threading.ThreadStart(AddressOf SubThreadProcess))
_SubThread.Name = "サブスレッド"
_SubThread.Start()
End Sub
'別スレッドで実行する処理
Private Sub SubThreadProcess()
'処理1
Threading.Thread.Sleep(1000)
'ReportProgress("処理1が終了しました。") 'この処理をメインスレッドで実行したい
OnProgress(New ProgressEventArgs("処理1が終了しました。")) 'この処理をメインスレッドで実行したい
'処理2
Threading.Thread.Sleep(1000)
'ReportProgress("処理2が終了しました。") 'この処理をメインスレッドで実行したい
OnProgress(New ProgressEventArgs("処理2が終了しました。")) 'この処理をメインスレッドで実行したい
'処理3
Threading.Thread.Sleep(1000)
'ReportProgress("処理3が終了しました。") 'この処理をメインスレッドで実行したい
OnProgress(New ProgressEventArgs("処理3が終了しました。")) 'この処理をメインスレッドで実行したい
End Sub
'いらない
'Private Sub ReportProgress(ByVal message As String)
' 'SynchronizingObjectが設定されていればInvoke、そうでなければ普通に実行
' If Not _SynchronizingObject Is Nothing Then
' _SynchronizingObject.Invoke( _
' New OnProgressDelegate(AddressOf OnProgress), _
' New Object() {message})
' Else
' OnProgress(message)
' End If
'End Sub
'OnProgressメソッド用のデリゲート
'Private Delegate Sub OnProgressDelegate(ByVal message As String)
'処理の途中経過を報告するイベント
Public Event Progress(ByVal sender As Object, ByVal e As ProgressEventArgs)
'Progressイベントを発生させる
Private Sub OnProgress(ByVal e As ProgressEventArgs)
'SynchronizingObjectが設定されていて、InvokeRequiredがTrueならInvoke
If ((Not ProgressEvent Is Nothing) AndAlso (Not _SynchronizingObject Is Nothing) AndAlso _SynchronizingObject.InvokeRequired) Then
_SynchronizingObject.BeginInvoke(ProgressEvent, New Object() {Me, e})
Else
RaiseEvent Progress(Me, e)
End If
End Sub
'Progressイベントのイベント変数クラス
Public Class ProgressEventArgs
Inherits EventArgs
Private _message As String
Public ReadOnly Property Message() As String
Get
Return _message
End Get
End Property
Public Sub New(ByVal message As String)
_message = message
End Sub
End Class
End Class
|
[ メッセージ編集済み 編集者: れい 編集日時 2005-11-01 06:37 ]
|
- kanai
- ベテラン
- 会議室デビュー日: 2004/09/13
- 投稿数: 98
|
投稿日時: 2005-11-02 16:10
れいさんが提示されたコードを試してみました。
こちらの方がコードがすっきりしていて読みやすく、いい感じです。
| 引用: |
|
Progressイベントのデリゲートが、ProgressEventという名前で
自動で定義されるというのが重要です。
|
なるほど、これは知りませんでした。参考になります。
ありがとうございました。
|