【问题标题】:How do I pass data from a thread using wxThreadEvent?如何使用 wxThreadEvent 从线程传递数据?
【发布时间】:2012-11-05 21:44:07
【问题描述】:

我有一个 GUI 和一个工作线程,我想将数据从工作线程发送到 GUI。我正在使用 QueueEvent 和 wxThreadEvents 来保持模型视图分离。我以某种方式遇到了 baadf00d 错误。

const int EvtID = 42;

MyFrame::MyFrame()
{
  ...
  // this seems to work correctly,
  //   but I'm including it in case it is part of the problem
  Bind(wxEVT_THREAD, (wxObjectEventFunction)&MyFrame::OutputData, this, EvtID);
  ...
}

MyFrame::OutputData(wxThreadEvent* event)
{
  // should get data from MyThread,
  //   but outputs 0xBA, 0xAD, 0xF0, 0x0D in successive calls
  output << event->GetInt();
}

MyThread::CreateOutputWithLocal()
{
  wxThreadEvent event(wxEVT_THREAD, EvtID);
  event.SetInt(getData());
  //pFrame is a wxEvtHandler*
  pFrame->QueueEvent(event.Clone());
}

MyThread::CreateOutputWithPointer()
{
  wxThreadEvent* event = new wxThreadEvent(wxEVT_THREAD, EvtID);
  event->SetInt(getData());
  //pFrame is a wxEvtHandler*
  pFrame->QueueEvent(event); // QueueEvent() takes control of the pointer and deletes it
}

使用wxThreadEventSetPayload()GetPayload() 或其SetExtraLong()GetExtraLong() 似乎没有任何区别。我需要什么才能让它工作?

【问题讨论】:

  • 这看起来不像真正的代码(缺少函数返回类型&c),所以问题可能出在您没有向我们展示的部分,因为似乎没有任何问题这里。好吧,您应该从 Bind() 参数中删除演员表,因为它是不必要的并且可能有害,否则我什么也看不到。
  • 谢谢。是的,问题出在代码的另一部分。这部分是准确传输数据的,但是获取数据的部分却搞砸了。
  • 啊,Bind() 不需要特定类型的函数指针,不像 Connect(),这是表单生成器使用的和我从中复制的。所以我的电话应该是Bind(wxEVT_THREAD, &amp;MyFrame::OutputData, this, EvtID);

标签: c++ multithreading wxwidgets


【解决方案1】:

Set/GetPayload 应该可以解决问题。可能是你做错了。您的代码将有更多帮助。但这里是一个剥离的例子,展示了这两种方法的用法。

Connect(wxID_ANY, wxEVT_COMMAND_DATA_SENT, wxThreadEventHandler(GMainFrame::OnAddText), NULL, this);//connect event to a method

void* MyThread::Entry(){
    wxThreadEvent e(wxEVT_COMMAND_DATA_SENT);//declared and implemented somewhere
    wxString text("I am sent!");
    e.SetPayload(wxString::Format("%s", text.c_str()));
    theParent->GetEventHandler()->AddPendingEvent(e);
    return NULL;
}


void GMainFrame::OnAddText(wxThreadEvent& event) {
    wxString t = event.GetPayload<wxString>();
    wxMessageBox(t);
}

我很久以前在玩 wxThreadEvent 时写的一个示例的剥离版本

【讨论】:

  • 谢谢。我可以在网上找到的用于处理 wxThreadEvent 的代码示例并不多,因此了解它应该如何设置肯定会有所帮助。
【解决方案2】:

在您的情况下,我只会将有效负载存储在属于框架的线程安全队列中。

在对事件进行排队之前,将数据放入线程安全队列中。在 OutputData 函数中,刷新队列并读取其中的数据。

我正在使用这种策略将boost::function &lt; void () &gt; 传递给 UI,因此它非常可扩展,因为我几乎可以从引擎线程触发任何事情。

【讨论】:

  • 这也可以,但是EvtHandler::QueueEvent() 已经是一种将数据传递到 UI 的线程安全方法,并且wxThreadEventGetPayload&lt;T&gt;()SetPayload&lt;T&gt;() 是模板化的,所以它们会获取任何类型的数据。当我正在使用的库中已经有了我需要的东西时,我不想包含 boost 库。
  • 啊,是的,好的。我忘了这样做。 :)
猜你喜欢
  • 1970-01-01
  • 2012-12-14
  • 2016-11-23
  • 2018-01-30
  • 1970-01-01
  • 2012-07-24
  • 1970-01-01
  • 1970-01-01
  • 2019-06-03
相关资源
最近更新 更多