0

懐かしさを感じていたので、リッチ テキスト ボックスにメッセージを表示する Windows フォームを備えたテキスト ベースの Adventure Game Creator IDE を開発しました。

BackgroundWorker を使用してストリームからテキスト ボックスにテキスト (ルームの説明とメッセージ) を送信するメッセージ ディスパッチャー クラスを作成しました。これは見事に機能しますが、小さな問題があります...

私がする必要があるのは、選択した任意の秒数の間、バックグラウンド ワーカーを一時停止/保持できるようにすることです。その理由は、アドベンチャー スクリプト言語には、HOLDn 秒間ゲームを一時停止する と呼ばれるステートメントがあるためです。

問題は、メッセージ ディスパッチャを使用してメッセージを表示していることです (蛇がやって来て、あなたを噛み、あなたは死ぬ....) が、メッセージが表示される前に HOLD ステートメントが実行されています。メッセージを最初に表示してからゲームを一時停止する必要があるため、これは私にとっては良くありません。

HOLD メソッドの実行コンテキストでは、次のようになりました。

Thread.CurrentThread.Join( _value * 10 );

私も試しました:

Thread.Sleep( _value * 10 );

これらはどちらも機能しないため、BackgroundWorker を何秒でも一時停止できるかどうかを尋ねています。

** 編集 **

のコードを追加しましたBackgroundWorker:

public delegate void OnReceiveData( object sender, StreamWatcherEventArgs e );

public class StreamWatcher
{
    public event OnReceiveData DataReceived = delegate { };

    private Stream _stream;

    public StreamWatcher( Stream stream )
    {
        _stream = stream;

        CreateWatcherThread();
    }

    private void CreateWatcherThread()
    {
        var bw = new BackgroundWorker();

        bw.DoWork += ( sender, args ) =>
        {
            while ( true )
            {
                if ( _stream.Length > 0 )
                {
                    Thread.CurrentThread.Join( 50 );

                    byte[] buf = new byte[ _stream.Length ];

                    _stream.Seek( 0, SeekOrigin.Begin );
                    _stream.Read( buf, 0, buf.Length );

                    string data = ASCIIEncoding.ASCII.GetString( buf );

                    DataReceived( this, new StreamWatcherEventArgs( data ) );

                    _stream.SetLength( 0 );
                }
            }
        };

        bw.RunWorkerAsync(); ;

    }

}

興味深いことに、これは実行中のスクリプトです。

IF ( VERB(7) AND NOUN(5) ) MESSLF(14) HOLD(200) EXIT END

これは基本的に、「GET SNAKE」と入力すると、メッセージ ディスパッチャーを介してテキスト ボックスにメッセージが表示され、ゲームが 2 秒間一時停止することを示しています。

問題は、一時停止がメイン スレッドで発生しているため、メッセージが表示される前に最初に一時停止が発生することです。

DataReceivedイベント ハンドラは次のとおりです。

_watcher.DataReceived += ( s, e ) =>
{
    if ( rtbOutput.InvokeRequired )
    {
        rtbOutput.Invoke( new Action( () =>
        {
            rtbOutput.AppendText( e.Data );
            rtbOutput.ScrollToCaret();
        } ) );
    }
    else
    {
        rtbOutput.AppendText( e.Data );
        rtbOutput.ScrollToCaret();
    }
};
4

0 に答える 0