具有后台工作者的MVP(引发异常)
本文关键字:异常 MVP 后台 工作者 | 更新日期: 2023-09-27 18:24:41
我的MVP解决方案遇到了一些问题,可能与线程有关。我正在运行Compact Framework 3.5并使用C#。我可以使用OpenNETCF,所以BackgroundWorker对我来说是可用的
我有一段代码(MyClient
),它使用套接字连接到web服务器。代码连接到服务器并下载数据(无休止地,它是一个流),直到用户停止它。因为数据的下载是无休止的,所以它必须在线程中运行,我认为这就是我遇到问题的地方。MyClient
对象具有一个状态,表示为枚举On
、Off
、Connecting
。编辑-只是澄清一下,当调用MyClient.Start()时,它会连接到服务器。然后,它获取该连接并将其保存,以便在线程运行中使用,以不断下载数据。因此,当调用Stop()时,它只需要获得一个bool标志来告诉MyClient内部使用的线程停止。为了清晰起见,下面是缩短的版本。
public void Start()
{
//...
//Code to Connect to server...
stream = _connection.GetStream();
//...
//Code to send/receive data to confirm connection...
State = State.On;
//Start thread to read data constantly until stopped by user setting "_continueReadingData = false"
_continueReadingData = true;
Thread readData = new Thread(ReadData);
readData.IsBackground = true;
readData.Start();
//Note readData uses the stream variable saved above
}
查看具有_presenter.TurnOn();
的呼叫演示者。演示者用_model.Start();
调用模型。其想法是启动MyClient代码,报告其状态变化,并在后台无休止地运行,直到用户单击停止。View
受到UI组件上Invoke/BeginInvoke调用的保护。
我在下面附上了我的模型的代码示例。最初我使用了一个普通的线程,并使其工作,正如你可以在下面看到的,它被注释掉了。这里有两个问题,需要使用Invoke将到达视图的所有内容编组回UI线程,还有这里的问题是,引发的任何异常都不会返回到UI线程,因此无法处理,并将导致应用程序崩溃。这是我试图解决的两个问题。
从那以后,我尝试了BackgroundWorker(在OpenNETCF中可用,就像.Net 2.0以后版本中的普通BackgroundWorkers一样),以按照下面的代码处理异常和编组。但有了这个,我无法让它发挥作用。相反,当状态更改并报告回GUI时。尽管调用了Invoke,但它会向InvalidOperationException - "Invoke or BeginInvoke cannot be called on a control until the window handle has been created"
抱怨。在做一些研究时,这听起来几乎像是线程在创建自己的一组控件。在这一点上,我感到困惑。
有人能帮我展示一下如何正确地启动/结束模型中的线程,使它们在后台运行,将异常带回要处理的模型,并将执行整理回UI线程,这样你就不必对每个控件都使用Invoke了。我相信这一定是可能的。
public class Model
{
public event EventHandler DataChanged;
public event EventHandler ErrorRaised;
private MyClient _client = new MyClient();
public Model()
{
//Register to events
_client.StateChanged += ClientStateChanged;
//Setup current values
State = _client.State;
}
void ClientStateChanged(NTRIPClient client, NTRIPState newState)
{
State = newState;
}
private State _state;
public State State
{
get { return _state; }
set
{
if (_state != value)
{
_state = value;
if (DataChanged != null)
{
DataChanged(this, EventArgs.Empty);
}
}
}
}
public void Start()
{
//Thread thread = new Thread(_NTRIPClient.Start);
//thread.IsBackground = true;
//thread.Start();
BackgroundWorker bgWorker = new BackgroundWorker();
bgWorker.DoWork += _client.Start();
bgWorker.RunWorkerCompleted += bgWorker_RunWorkerCompleted;
}
void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if(e.Error != null)
{
if (ErrorRaised != null)
{
ErrorRaised(this, new ErrorEventArgs(e.Error));
}
}
}
}
问题是在视图中创建演示者,而视图又创建了模型。此模型是在视图完全构建之前调用的,因此控件尚未创建。
由于一个简单的错误,出现了一个大问题:)