MFC,多线程,static控件程序中的仿佛是更新卡死的问题,敬请各位高手解答!

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MFC,多线程,static控件程序中的仿佛是更新卡死的问题,敬请各位高手解答!相关的知识,希望对你有一定的参考价值。

我在App类中创建了一个纤程,在ThreadFunc()中调用view类中的一个函数MoveWord(),在此函数中我创建了一个CStatic对象,并Set上一个资源位图,并设下一个for循环,让此控件在窗口内MoveWindow(),当控件坐标移动到边界时就把它movewindow到对面边界。
但由于控件坐标在左上角,当控件移动到右下边界时有一部分会离开客户区,由此引发了Static控件需要ReDrawWindow(),我发现当此控件上的全部图片被遮挡时就会导致程序卡死,并且子线程开始运行时若移动或最小化窗口则也会引发窗口卡死,我怀疑是某些原因导致 程序无法正常刷新窗口造成的,但无法找到原因,请大侠们赐教!
一下为纤程主要代码:
void CTestView::MoveWord()

CStatic* pStatic = new CStatic();
CRect rect(0,0,50,50);
pStatic->Create(NULL,WS_CHILD|WS_VISIBLE|SS_BITMAP,(RECT)rect,this,i++);
pStatic->SetBitmap(LoadBitmap(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDB_BITMAP1)));
int wx = 0;
int wy =0;
int x = 0;
int y =0;
CClientDC dc(this);
CRect aRect;
GetClientRect(aRect);
CPoint point;
for(;;)

//aStatic.RedrawWindow();
wx = wx+2;
wy = wy +2;
x = wx+25;
y = wy+25;
GetCursorPos(&point);
this->ScreenToClient(&point);
if(abs(point.x-x) >= abs(point.y -y))

if( abs(point.x - x)<25 && abs(point.y -y)<25 && point.y>=0 && point.y<= aRect.bottom)

if(point.x >x)
x = point.x -25;
else
x = point.x + 25;

if( abs(point.x - x)<25 && abs(point.y -y)<25 && point.y>=0 && point.y<= aRect.bottom)

if(point.y >y)
y = point.y -25;
else
y = point.y +25;



else

if( abs(point.x - x)<25 && abs(point.y -y)<25 && point.y>=0 && point.y<= aRect.bottom)

if(point.y >y)
y = point.y -25;
else
y = point.y +25;


if( abs(point.x - x)<25 && abs(point.y -y)<25 && point.y>=0 && point.y<= aRect.bottom)

if(point.x >x)
x = point.x -25;
else
x = point.x + 25;


wx = x -25;
wy = y -25;
if(wx >= aRect.right || wx<=0)
wx =0;
if(wy >= aRect.bottom ||wy <= 0)
wy =0;
pStatic->MoveWindow(wx,wy,50,50,TRUE);
::Sleep(50);



怎么会一直占用cpu呢?坐标是相对于客户区而言的,拖不拖这语句都是一样执行的,另外,这是个多线程函数根本不会说能完全占用cpu,再说了,即使能占用后边还有一个sleep(50),有这50毫秒也足以做任何事了。后来我上网查了查,导致这个错误的根本原因是子线程调用主线程的控件,当我把每次的坐标改变作为一个消息传递给主线程并由主线程处理控件移动时这个问题就消失了。

参考技术A if(abs(point.x-x) >= abs(point.y -y))

if( abs(point.x - x)<25 && abs(point.y -y)<25 && point.y>=0 && point.y<= aRect.bottom)

if(point.x >x)
x = point.x -25;
else
x = point.x + 25;

if( abs(point.x - x)<25 && abs(point.y -y)<25 && point.y>=0 && point.y<= aRect.bottom)

if(point.y >y)
y = point.y -25;
else
y = point.y +25;


你拖动时,这句一直占有cpu,没法执行Redraw操作。自然挂掉了。

在 MFC 中实现多线程以更新外部函数可访问的内部字典

【中文标题】在 MFC 中实现多线程以更新外部函数可访问的内部字典【英文标题】:Implementing Multithreading in MFC to update an internal dictionary accessible by outside functions 【发布时间】:2011-12-20 17:54:15 【问题描述】:

我正在使用 C++ 和 MFC 创建一个应用程序,该应用程序将实时从 Bloomberg 中提取信息。 Bloomberg API 有一个订阅类,可以“订阅”来自 Bloomberg 的更新并将它们实时推送到我的 PC,因此我需要在线程中运行一个事件循环来处理 Bloomberg 数据。

为了节省带宽,我想使用字典将Bloomberg股票代码映射到它的最后价格,所以程序不会为同一个股票代码获得多个结果(即我多次拥有相同的股票代码),程序将在字典中查找。这样,我只需要订阅不同的股票代码。

我以前没有使用过多线程,我一直在阅读 MSDN 中的文档,但我很难理解我需要做什么。

根据我的理解,我需要使用 AfxBeginThread() 创建一个工作线程,并传入一个指向字典实例的指针。工作线程将在我的程序的其余部分运行时更新字典。

这个字典被线程锁定了吗?我可以在更新时安全地访问它吗?

我可以让线程在后台运行直到程序终止吗?当我终止程序时是否需要显式终止线程还是会自动完成?

这听起来对吗,还是我错过了一些基本的东西?

所以我创建了一个 CMap(CString,LPCSTR,double, double) 来存储代码和定价。 我通过 LPVOID 传递一个指向 CMap 的指针,并且 CMap 得到实时更新。现在一切正常。我可以在 CMap 中查找变量并获得实时定价。

但是,现在,它不是“线程安全的”。只有一个线程向 CMap 写入数据,其他一切都只是读取 CMap 中的数据,所以现在,这没什么大不了的。

但是,为了学习良好的编程实践,我应该在写入 CMap 时使用 CEvent 吗? CEvent 应该被传递到线程中吗?我不确定这是如何实现的。我做了一个快速的谷歌搜索,我没有找到任何关于如何在线程中锁定和解锁变量的信息。

【问题讨论】:

这个问题非常广泛,不确定你会得到多少帮助。我已经尽我最大的努力尝试让您入门,但最好的建议是通读该答案并开始尝试。如果您可以回复具体问题,您将更有可能获得帮助。 【参考方案1】:

任何不是专门设计为线程安全的对象都不是这样。因此,您将需要一些互斥对象来保护您的“字典”的访问:

// for example, HINT CCriticalSection, or CSemaphore
mutex.lock();
dictionary.add(...);
mutex.unlock();

虽然在上述情况下文档会建议使用CSemaphore,但CCriticalSection(在我看来)对于初学者来说更容易理解。

您的应用程序启动的线程应该由您的应用程序停止,是的。您可以通过向线程发出工作已完成的信号来做到这一点:

// for example, HINT CEvent
while(!stopped)

   do_work();

并在应用程序退出时设置停止事件。

对于初学者,请阅读here。老实说,虽然这些都是非常基本的问题,所以要准备好花时间好好学习这些东西。如果编写适当的多线程代码很容易,那么每个人都会这样做。

至于我提到的具体同步类,有文档here。

【讨论】:

以上是关于MFC,多线程,static控件程序中的仿佛是更新卡死的问题,敬请各位高手解答!的主要内容,如果未能解决你的问题,请参考以下文章

[转]MFC子线程中更新控件内容的两种办法

在 MFC 中实现多线程以更新外部函数可访问的内部字典

[转]MFC子线程更改图像数据后更新主窗口图像显示方法

转:MFC中创建多线程

MFC 功能包 - 如何更新属性网格控件

MFC 请教怎样设置STATIC TEXT控件的字体大小和颜色