2017-12-05 14 views
3

私はC#でWindowsフォームプロジェクトを持っています。このプロジェクトには別のスレッドで再生されるWaveOutデバイスがあります。この再生スレッドは、定期的にUIスレッドメソッドを呼び出し、それに何らかのデータ(サウンドカードに渡されているオーディオ情報を保持する配列)を渡す必要があります。 passAudioメソッドは、接続されたEventHandlerを定期的に呼び出します。C#で呼び出すためにUIメソッドを別のスレッドに渡す

は今、waveoutデバイス(WaveOutPlayer.cs)はイベントハンドラを持っています

public class WaveOutPlayer : IDisposable 
{ 
    public event EventHandler<AudioEventArgs> BufferSwapped; 
    ... 
    private void passAudio(byte[] pAudiodata) 
    { 
     AudioEventArgs args = new AudioEventArgs(); 
     args.Data = pAudiodata; 
     args.WaveFormat = ws.Format; 
     if (BufferSwapped != null) 
     { 
      BufferSwapped.Invoke(this, args); 
     } 
    } 
} 

また、Windowsフォームのインスタンスは、このイベントハンドラに接続します。

private void Start() 
{ 
    WaveStream Audio = new WaveStream("sine440hz_16bit_stereo.wav"); 
    WaveOutPlayer wp = new WaveOutPlayer(audio, 0); 
    wp.BufferSize = 8192; // testing 
    wp.Repeat = false; // 'true' not implemented yet 
    wp.BufferSwapped += Wp_BufferSwapped; 
} 

private void Wp_BufferSwapped(object sender, AudioEventArgs e) 
{ 
    // The audio buffer data can be found in the event args. 
    // So analyze this Audio and manipulate some of the forms' controls 
    // accordingly. 

    this.labelForAmplitude.Text = "some value"; 
} 

しかし、これは例外が発生しますWp_BufferSwapped-Methodは実際に再生スレッドに属しているため、ラベルのテキストを操作できない可能性があります。

Now: Windowsフォームのコードをより難しくすることなくこの問題を解決するにはどうすればよいですか?その理由は、私の学生(高等学校)が配列と簡単なユーザーインターフェイスでいくつかのクールなものをやり遂げることができるようにするためです。しかし、現時点では、ユーザーインターフェース作業について非常に基本的な知識しかありません。彼らはまだBeginInvokeやMethodInvokerのようなものについては何も知らない。 WaveOutPlayerをDLLの形で与えたいのですが、Windowsフォームに対処する必要があります。 この特定の種類の問題を解決する方法はありますか?

+0

'this.labelForAmplitude.Text'を' ref'to 'Wp_BufferSwapped-Method'として送ることができます –

+0

[C#の別のスレッドからGUIを更新するにはどうすればいいですか?](https://stackoverflow.com)/question/661561/how-do-i-update-the-another-thread-in-c) – PaulF

+0

@Usmanlqbal変更するラベルが1つまたは2つしかない場合は、解決策になります。しかし、どのラベルや絵の枠を変更するかを学生に決定させたいと思っています。 – AudioGuy

答えて

1

あなたはこのように、それにあなたのイベントハンドラの呼び出しをコンストラクタで現在SynchronizationContextをキャプチャしPostことができます。同じ時間がないでいる間、あなたのWaveOutPlayerにリサイズへの依存性を導入していない。これにより

public class WaveOutPlayer { 
    private readonly SynchronizationContext _context; 
    public WaveOutPlayer() { 
     // capture 
     _context = SynchronizationContext.Current; 
    } 

    public event EventHandler<AudioEventArgs> BufferSwapped; 

    private void passAudio(byte[] pAudioData) { 
     var args = new AudioEventArgs(); 
     args.Data = pAudioData; 
     var handler = BufferSwapped; 
     if (handler != null) { 
      if (_context != null) 
       // post 
       _context.Post(_ => handler(this, args), null); 
      else 
       handler(this, args); 
     } 
    } 
} 

WinFormsの部分からはコンパイルされたアクションが必要です。イベントハンドラはUIスレッド上で呼び出されます。ここでPostは、Control.BeginInvokeのアナログになります。 Control.Invokeのアナログが必要な場合は、代わりにSendを使用してください。

+0

完璧に動作します!どうもありがとうございました!! – AudioGuy

関連する問題