Onsunsl 发表于 2011-8-9 22:50:42

VC6在线程中对进度操作为什么会报错?

VC6在线程中对进度操作为什么会报错?

在界面上放一个按钮,当点击按钮时,读取控件的值,后创建一个线程,并把这些值传到线程中,让线程刷新进度条件,从而解放界面的其它操作。

可是在线程中对进度条件的指针操作时程序直接崩溃了。不知道什么原因,各位帮忙看看是什么问题导致的?

声明:
struct TestThreadInfo
{
    CProgressCtrl* pctrlProgress;
        UINT BeginValue;
        UINT EndValue;
        UINT StepValue;
        UINT StepTime;
        int Ctrl;
};
UINT TestThreadFunc(LPVOID lpParam);




按钮消息处理:

void Test::OnButtonTestStart()
{
        // TODO: Add your control notification handler code here
        UpdateData(TRUE);
        if (Teststate = FALSE)
        {
                TestThreadPara.pctrlProgress = &m_PrintTestProgress;
                TestThreadPara.BeginValue    = m_EditBeginFocus;
                TestThreadPara.EndValue      = m_EditEndFocus;
                TestThreadPara.StepTime      = m_EditPrintTime;
                TestThreadPara.StepValue   = m_EditFocusD;
                TestThreadPara.Ctrl          = TRUE;
                Teststate = TRUE;
        }
        else
                Teststate = TRUE;

        pThread=AfxBeginThread(TestThreadFunc, &TestThreadPara);
}






线程体:

UINT TestThreadFunc(LPVOID lpParam)
{
    TestThreadInfo* pInfo=(TestThreadInfo*)lpParam;
    for(int i=0;i<100;i++)
    {
      int nTemp=pInfo->StepTime;
         pInfo->pctrlProgress->SetPos(i);
      
      Sleep(nTemp);
    }
    return 0;
}




程序运行到pInfo->pctrlProgress->SetPos(i);时直接崩溃了。

Onsunsl 发表于 2011-8-9 22:52:32

http://cache.amobbs.com/bbs_upload782111/files_44/ourdev_666027LX86VS.jpg
(原文件名:未命名.jpg)

maxbiger 发表于 2011-8-10 00:12:20

进度条之前有没有初始化? 就是设定范围。。。

或者把 线程 函数弄成友员函数

Onsunsl 发表于 2011-8-10 07:07:07

已经初化了
        m_StaticTestPercentage = "0%";
        m_PrintTestProgress.SetRange(0,99);

Onsunsl 发表于 2011-8-10 07:09:57

我尝试着把线程设成Test类的静态成员也不行

maxbiger 发表于 2011-8-10 08:11:02

TestThreadInfo之前难道不加 struct 吗??

你的 进度条 应该是 对话框类的吧,直接在

线程函数 里面 用对话框类 指针访问进度条看看

我就是 这么做的。。。

不过我用另外 一个创建线程 的函数,忘记了。。。

你都试试。。

Onsunsl 发表于 2011-8-10 09:11:36

不是struct的问题,将它的声明处改成typedef也不行

我是将进度条控制变量的指针存在结构体里传过去的,

TestThreadPara.pctrlProgress = &m_PrintTestProgress;

Onsunsl 发表于 2011-8-10 09:12:27

你说的线程函数是CreateThread()吧?

zc3909 发表于 2011-8-10 09:30:42

跟踪一下,看看pInfo->pctrlProgress句柄对不对

racede 发表于 2011-8-10 10:04:23

一般不推荐这样访问mfc控件,会产生很多问题,速度过快时尤其。应该用对界面发送消息的形式来控制控件。

118139 发表于 2011-8-10 11:23:58

这里有10多线程例子,例3跟例5 跟你上面的代码一模一样

点击此处下载 ourdev_666128TZCWPU.rar(文件大小:637K) (原文件名:多线程10例.rar)

Onsunsl 发表于 2011-8-13 00:24:13

搞定了,感谢大家的支持,我有义务把解决方法给写出来,方法是:在线程中给界面发消息,这也是最安全的方法。

1、在把OnButtonTestStart()处创建线程时,把界面的句柄传给线程

2、在线程处理完数据后,发一个消息给界面。

3、在界面中手动增加一个消息处理模块,用于刷新进度条。

Onsunsl 发表于 2011-8-13 00:29:37

回复【10楼】118139
这里有10多线程例子,例3跟例5 跟你上面的代码一模一样
点击此处下载(原文件名:多线程10例.rar)

-----------------------------------------------------------------------

惭愧,你传的这10个例子也是我看了一个高手的教程然后按教程写的,虽然跟着写了遍,但刚才VC遇了问题就蒙了


我的解决办法也正是里面的例7,呵呵,惭愧,惭愧

连接:http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=4870136&bbs_page_no=1&search_mode=3&search_text=Onsunsl&bbs_id=9999

sdjiangyi 发表于 2011-8-15 17:49:44

晕, 搞电子的朋友们, 软件可复杂啦。

所有界面组件,都是非线程安全的, 也就是说只能有一个线程使用它,你的程序启动后, 主线程在使用它们, 你自己创建的线程, 如果强行访问它们,绝对会报错。
一个程序启动一个进程,一个进程里有一个主线程。
一般来说, 自己创建的线程, 只用来进行数值运算和底层api调用。 如果需要和界面通讯, 绝对不可以直接控制界面组件, 必须通过postmessage 或者sendmessage等方式来传递消息。如果访问主进程里的变量, 可以用锁互斥等技术,但是如果设计巧妙也可以不用,或者对变量仅仅进行读操作!!

尽可能避免创建线程, 如果一定要创建, 尽可能减少创建销毁线程次数, 让一个线程处理数据后, 自动睡眠挂起, 然后有数据了再复活处理数据。。。。 线程的创建开销是很大的。 如果线程太多, 你还得用api对线程的优先级进行处理。。。。

lyw123 发表于 2011-9-7 14:34:03

不是struct的问题,将它的声明处改成typedef也不行

我是将进度条控制变量的指针存在结构体里传过去的,

TestThreadPara.pctrlProgress = &m_PrintTestProgress
页: [1]
查看完整版本: VC6在线程中对进度操作为什么会报错?