DOBON.NET DOBON.NETプログラミング掲示板過去ログ

排他制御

  • 題名: 排他制御
  • 著者: そーですねぃ
  • 日時: 2006/10/03 14:59:19
  • ID: 17771
  • この記事の返信元:
    • (なし)
  • この記事への返信:
  • ツリーを表示
環境/言語:[言語:C# 2005 OS:XP Pro]
分類:[.NET]

お世話になります。

下記のコードにてコンソール画面の排他制御を企てています。
タイマにて500msごと、ボタンにて非同期に、Outputメソッド
を実行します。
タイマにてOutputメソッド実行している間にボタンを押した
場合にはボタン押下によるOutputメソッドはlockにより実行
を拒否され、出力結果は button: 1 〜 button: 5 と timer: 1
〜 timer: 5の組み合わせが交互にあらわれるものと考えて
いました。
が、出力結果は以下の通りです。
lockをMutexに変えてみても同様の結果に終わりました。
何故当方の期待通りの結果にはならないのでしょうか。
お知恵をお貸し願います。宜しくお願い致します。

【コード】
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace misctest
{

public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
timer1.Enabled = true;
}

private void button1_Click(object sender, EventArgs e)
{
Output("button");
}

private void timer1_Tick(object sender, EventArgs e)
{
Output("timer ");
}

private bool Output(string param)
{
lock (this)
{
Console.WriteLine("{0}: 1", param);
Application.DoEvents();
Thread.Sleep(100);
Console.WriteLine("{0}: 2", param);
Application.DoEvents();
Thread.Sleep(100);
Console.WriteLine("{0}: 3", param);
Application.DoEvents();
Thread.Sleep(100);
Console.WriteLine("{0}: 4", param);
Application.DoEvents();
Thread.Sleep(100);
Console.WriteLine("{0}: 5", param);
}
return true;
}
}
}

【出力結果】
button: 1
button: 2
button: 3
button: 4
timer : 1
timer : 2
timer : 3
timer : 4
timer : 5
button: 5
timer : 1
timer : 2
timer : 3
timer : 4
timer : 5
timer : 1
timer : 2
timer : 3
timer : 4
button: 1
button: 2
button: 3
button: 4
button: 5
timer : 5
System.Windows.Forms.Control の Click イベントも System.Windows.Forms.Timer の Tick イベントも非同期ではありません。どちらも同じスレッドでイベントハンドラが動作します。
ですので、Output メソッドを呼ぶのがこの二つだけなら、このメソッドの lock に意味はありません。
// Application.DoEvents がポイントです。
  • 題名: Re[2]: 排他制御
  • 著者: そーですねぃ
  • 日時: 2006/10/04 9:34:30
  • ID: 17777
  • この記事の返信元:
  • この記事への返信:
  • ツリーを表示
返信有難うございます。
イベントとスレッドの違いが良く理解できていなかったようです。
同様にMutexもスレッド間での排他は可能だが同一スレッドでは無意味ということですね。

では、上記のケースでタイマイベントの処理中にボタンイベントが発生した場合、タイマイベントの処理終了を待ってボタンイベントの処理を行うにはどのような手法があるのでしょうか。
ボタンイベント内でSleepを行うとタイマイベントの処理も止まってしまいます。

今回のコードはテスト用にコンソールへの表示としましたが、実際にはシリアル通信を排他したいと思っています。このシリアル通信コントロールはイベントを発せさせる側のスレッドで作成します。非同期イベントの場合は別スレッドでの呼び出しとなるので制御できないように思います。
何かヒントをご教示願えませんでしょうか。宜しくお願い致します。
> では、上記のケースでタイマイベントの処理中にボタンイベントが発生した場合、タイマイベントの処理終了を待ってボタンイベントの処理を行うにはどのような手法があるのでしょうか。

そんなものはありません。
同一スレッドで行われる処理を並行化するのは不可能です。

並行化したい処理はスレッド化するのが自然なな設計です。
この場合はタイマハンドラで実行している一連の処理をスレッド化するのが妥当でしょう。
  • 題名: Re[4]: 排他制御
  • 著者: そーですねぃ
  • 日時: 2006/10/04 10:35:27
  • ID: 17781
  • この記事の返信元:
  • この記事への返信:
    • (なし)
  • ツリーを表示
> 並行化したい処理はスレッド化するのが自然なな設計です。
> この場合はタイマハンドラで実行している一連の処理をスレッド化するのが妥当でしょう。
>
なるほど。わかりました。
スレッドについて理解できていない部分もあり、非常に勉強になりました。
もう一度処理を見直しスレッドを使用した並行処理を作成しようと思います。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板