懐かしさを感じていたので、リッチ テキスト ボックスにメッセージを表示する Windows フォームを備えたテキスト ベースの Adventure Game Creator IDE を開発しました。
BackgroundWorker を使用してストリームからテキスト ボックスにテキスト (ルームの説明とメッセージ) を送信するメッセージ ディスパッチャー クラスを作成しました。これは見事に機能しますが、小さな問題があります...
私がする必要があるのは、選択した任意の秒数の間、バックグラウンド ワーカーを一時停止/保持できるようにすることです。その理由は、アドベンチャー スクリプト言語には、HOLD
n 秒間ゲームを一時停止する と呼ばれるステートメントがあるためです。
問題は、メッセージ ディスパッチャを使用してメッセージを表示していることです (蛇がやって来て、あなたを噛み、あなたは死ぬ....) が、メッセージが表示される前に 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();
}
};