【发布时间】:2015-04-07 16:51:51
【问题描述】:
我正在使用来自 WxWidget wiki 的示例来了解如何进行线程间和进程间通信。我不知道为什么该示例有效,但我的代码非常相似,不在“m_QueueCount.Wait(); // 等待信号量(=队列计数变为正数)”行处
当我运行代码时,会显示一个异常:
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;
【问题讨论】:
标签: c++ visual-studio-2013 wxwidgets