我感到很怀旧,并开发了一个基于文本的冒险游戏创建器IDE,它有一个Windows窗体,可以向富文本框显示消息。
我编写了一个消息调度程序类,它将使用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();
}
};