信号灯wxwidgets出现异常
Exception with semaphore wxwidgets
我使用WxWidget wiki中的一个示例来了解如何进行线程间和进程间通信。我不知道为什么这个例子有效,但我的代码非常相似,在"m_QueueCount.Wait();//等待信号量(=队列计数变为正)"行不起作用
当我运行代码时,会显示一个exeption:
TeamTranslate.exe中0x00B2DB61处的首次机会异常:0xC0000005:读取位置0x00000078时发生访问冲突。
如果有此异常的处理程序,则程序可能是安全的继续。
断点在xstring文件的第1749行。这是代码:
size_type length() const _NOEXCEPT
{ // return length of sequence
return (this->_Mysize);
}
我希望有人能告诉我为什么这不起作用!
提前谢谢。
标题:
class QueueMSG
{
public:
QueueMSG(wxEvtHandler* pParent) : m_pParent(pParent) {}
void AddJob(MessagePTR job); // push a job with given priority class onto the FIFO
MessagePTR Pop();
void Report(const Message::tCOMMANDS& cmd, MessagePTR arg); // report back to parent
size_t Stacksize(); // helper function to return no of pending jobs
private:
wxEvtHandler* m_pParent;
std::vector<MessagePTR> m_Jobs; // multimap to reflect prioritization: values with lower keys come first, newer values with same key are appended
wxMutex m_MutexQueue; // protects queue access
wxSemaphore m_QueueCount; // semaphore count reflects number of queued jobs
};
class WorkerThread : public wxThread
{
public:
WorkerThread(QueueMSG* pQueue) : m_pQueue(pQueue) { wxThread::Create(); }
private:
QueueMSG* m_pQueue;
BingTranslate bng;
virtual wxThread::ExitCode Entry();
virtual void OnJob();
}; // class WorkerThread : public wxThread
cpp:
void QueueMSG::AddJob(MessagePTR job) // push a job with given priority class onto the FIFO
{
wxMutexLocker lock(m_MutexQueue); // lock the queue
m_Jobs.push_back(job); // insert the prioritized entry into the multimap
m_QueueCount.Post(); // new job has arrived: increment semaphore counter
} // void AddJob(const tJOB& job, const tPRIORITY& priority=eNORMAL)
MessagePTR QueueMSG::Pop()
{
std::vector<MessagePTR>::iterator element;
m_QueueCount.Wait(); // wait for semaphore (=queue count to become positive)
m_MutexQueue.Lock(); // lock queue
element = m_Jobs.begin(); // get the first entry from queue (higher priority classes come first)
m_Jobs.erase(m_Jobs.begin()); // erase it
m_MutexQueue.Unlock();// unlock queue
return *element; // return job entry
} // tJOB Pop()
void QueueMSG::Report(const Message::tCOMMANDS& cmd, MessagePTR arg) // report back to parent
{
wxThreadEvent evt(wxEVT_THREAD, wxID_ANY);// cmd); // create command event object
evt.SetPayload<MessagePTR>(arg); // associate string with it
wxQueueEvent(m_pParent, evt.Clone());
//m_pParent->AddPendingEvent(evt); // and add it to parent's event queue
} // void Report(const tJOB::tCOMMANDS& cmd, const wxString& arg=wxEmptyString)
size_t QueueMSG::Stacksize()
{
wxMutexLocker lock(m_MutexQueue); // lock queue until the size has been read
return m_Jobs.size();
}
void WorkerThread::OnJob()
{
MessagePTR job = m_pQueue->Pop(); // pop a job from the queue. this will block the worker thread if queue is empty
bng.translateThis(job);
switch (job->m_cmd)
{
case Message::eID_THREAD_EXIT: // thread should exit
//Sleep(1000); // wait a while
throw Message::eID_THREAD_EXIT; // confirm exit command
case Message::eID_THREAD_JOB: // process a standard job
//Sleep(2000);
m_pQueue->Report(Message::eID_THREAD_JOB, job); // report successful completion
break;
case Message::eID_THREAD_JOBERR: // process a job that terminates with an error
m_pQueue->Report(Message::eID_THREAD_JOB, job);
//Sleep(1000);
throw Message::eID_THREAD_EXIT; // report exit of worker thread
break;
case Message::eID_THREAD_NULL: // dummy command
default: break; // default
} // switch(job.m_cmd)
} // virtual void OnJob()
wxThread::ExitCode WorkerThread::Entry()
{
Message::tCOMMANDS iErr;
m_pQueue->Report(Message::eID_THREAD_STARTED, NULL); // tell main thread that worker thread has successfully started
try {
while (true)
OnJob();
} // this is the main loop: process jobs until a job handler throws
catch (Message::tCOMMANDS& i) {
m_pQueue->Report(iErr = i, NULL);
} // catch return value from error condition
return (wxThread::ExitCode)iErr; // and return exit code
} // virtual wxThread::ExitCode Entry()
消息类别:
#pragma once
#include <cstring>
#include <stdio.h>
#include <wx/string.h>
#include <vector>
#include <memory>
enum MSGDirection{
in,
out
};
class Message {
public:
enum tCOMMANDS // list of commands that are currently implemented
{
eID_THREAD_EXIT = wxID_EXIT, // thread should exit or wants to exit
eID_THREAD_NULL = wxID_HIGHEST + 1, // dummy command
eID_THREAD_STARTED, // worker thread has started OK
eID_THREAD_JOB, // process normal job
eID_THREAD_JOBERR // process errorneous job after which thread likes to exit
}; // enum tCOMMANDS
Message(MSGDirection dir, wxString from, wxString message, wxString language_org, wxString language_dest) : m_message(message), m_dir(dir), m_from(from), m_language_orig(language_org), m_language_dest(language_dest), m_cmd(eID_THREAD_EXIT){
time_t rawtime;
struct tm* timeinfo;
char timestamp[100];
time(&rawtime);
timeinfo = localtime(&rawtime);
strftime(timestamp, 100, "%c", timeinfo);
m_timestamp = timestamp;
}
Message() : m_cmd(eID_THREAD_NULL) {}
~Message(){ }
void setIO(MSGDirection dir);
MSGDirection getIO(){ return m_dir; };
void setFrom(char* dir);
wxString getFrom(){ return m_from; };
void setMSG(wxString dir){
m_message = dir;
};
wxString getMSG(){ return m_message; }
wxString getTranslated(){ return m_translated; }
wxString getTimeStamp(){ return m_timestamp; }
wxString getLanguageOrig(){ return m_language_orig; }
wxString getLanguageDest(){ return m_language_dest; }
void setSrtTranslate(wxString str){ m_translated = str; }
tCOMMANDS m_cmd;
private:
MSGDirection m_dir;
wxString m_language_orig;
wxString m_from;
wxString m_message;
wxString m_timestamp;
wxString m_language_dest;
wxString m_translated;
};
typedef std::shared_ptr<Message> MessagePTR;
typedef std::shared_ptr<std::vector<MessagePTR>> MessageQueuePTR;
在QueueMSG::Pop()
调用中,即使迭代器无效,也要使用它。即使它没有被对erase
的调用所无效(它将是这样的,请参阅此处),您也不能保证在解锁互斥对象后对其进行验证,因为此时您可以进行时间切片,然后另一个线程可以修改容器。因此,您应该改为:
MessagePtr msg;
m_QueueCount.Wait();
{
wxMutexLocker lock( m_MutexQueue );
auto element = m_Jobs.begin();
msg = *element;
m_Jobs.erase(element);
}
return msg;
在他们的代码中——与您的代码略有不同——他们取消引用迭代器以获得一对,并通过以下行返回包含的第二个元素:
element=(m_Jobs.begin())->second; // that '->'
这就是为什么他们不会遭受不明确的行为。
相关文章:
- 处理多个异常集合的C++方法
- 我在c++代码中生成了一个运行时#3异常
- 孤立代码块在结构中引发异常
- C++中的赋值发生,尽管右侧出现异常
- 从构造函数抛出异常时如何克服内存泄漏
- 异常属于C++中的线程还是进程
- 当类定义不可见时捕获异常
- 引发异常:读取访问冲突**dynamicArray**为0x1118235.发生
- 为什么异常不退出程序?
- 为什么我应该在异常处理中使用std::cerr而不是std::cout
- 如何修复链表类实现的未处理异常0xDDDDDDDD
- 关于:C++中异常对象的范围:为什么我没有得到副本?
- 是什么导致了Unity 3D中的"错误线程异常"?
- 什么是事件表 (wxWidgets)?
- 如何将strftime中的格式错误作为异常捕获
- 创建具有 new in 函数和"this is nullptr"异常的对象
- 尝试使用智能指针时引发异常
- 尝试使用 wxWidgets 从 zip 打开不存在的文件时无法捕获的异常
- 信号灯wxwidgets出现异常
- wxWidgets - 终止调用而没有活动异常(使用 std::thread)