Re: Проблема с потоками
От: Pavel Dvorkin Россия  
Дата: 13.07.14 02:34
Оценка: +2
Здравствуйте, SmileIlya, Вы писали:

SI>Создал семафор[10][10]

SI>в этом потоке запускаю кол-во потоков согласно семафору(10) в качестве параметра передаю значение из вектора

Так 10 или 10*10 ?

По описанию проблемы сказать вряд ли что-то возможно, нужны более подробные сведения. Пока что не совсем понятно, зачем тут семафоры вообще.

Запускаем поток-менеджер. У него очередь для записей. Он запускает рабочие потоки (а лучше пул потоков) и передает им очередную запись. Они ставят его в известность об окончании через PostThreadMessage, в обработчике которой он принимает к сведению, что очередную запись обработали и запускает новый поток, передавая ему следующую запись (или дает новое задание пулу). Кстати, пулу можно и больше заданий дать, чем есть потоков, он сам разберется, правда, порядок при этом не определен, так и сейчас определен только порядок, в котором обработка начинается, но не порядок, в котором обработка записей заканчивается. Это вообще существенно — в каком порядке записи обрабатывать ?

Очередь синхронизировать не надо, так как с ней имеет дело только поток-менеджер. Для отображения та же PostThreadMessage, вызываемая или из рабочего, или из менеджера (чтобы не прыгать через голову начальника ) , только основному потоку (GUI), который только и будет обновлять вид.

По окончании своей работы поток-менеджер опять же через PostThreadMessage шлет сообщение GUI потоку о том, что он все сделал , и тихо заканчивается сам.
With best regards
Pavel Dvorkin
Re[12]: Проблема с потоками
От: Кодт Россия  
Дата: 16.07.14 12:55
Оценка: 1 (1)
Здравствуйте, Carc, Вы писали:

C>Не проще ли отослать фрейму сообщение с данными, а он уже разгребая очередь сам обновит данные в строке.


И тут сразу встанет вопрос о сериализации этих данных.

C>Достаточно сказать гуевому потоку, мол измени, а он сам разрулит.


Об том и речь. Пусть гуёвый поток умеет читать и публиковать данные в любой момент времени, а рабочий только сообщает, что пришла пора обновиться.
Перекуём баги на фичи!
Re[14]: Проблема с потоками
От: Кодт Россия  
Дата: 16.07.14 14:49
Оценка: 1 (1)
Здравствуйте, Carc, Вы писали:

К>>И тут сразу встанет вопрос о сериализации этих данных.

C>Да ну, какой там вопрос? Вариантов то немного: SendMesage(...., (LPARAM)указатель_на_данные_на_стеке),

Разложить грабли для дедлока, я уже написал об этом

C>или PostMessage/PostThreadMessageSendMesage(...., (LPARAM)new (наши_данные)), а гуевый поток уж освободит память.


Ходьба по канату.
Не знаю, как у других, а я давно уже понял, что отдавать владеющие указатели в свободное плавание по виндовской очереди сообщений — рискованно.
Ибо придётся заботиться о гарантированной доставке, и программа становится слишком плотно связанной.
Перекуём баги на фичи!
Проблема с потоками
От: SmileIlya  
Дата: 12.07.14 15:05
Оценка: -1
Доброго всем дня!
Есть проблема с потоками, может я что-то не так делаю или мысли не туда идут.
Есть задача: есть вектор данных ~3500 значений
В программе необходимо запустить обработку этих данных, приложение зависать не должно и пользователь должен видеть сколько записей обработано, сколько осталось.
Небольшой нюанс, есть записи которые обрабатываются продолжительное время.
моя реализация.
Создал семафор[10][10]
запустил || поток (дабы не зависло приложение)
в этом потоке запускаю кол-во потоков согласно семафору(10) в качестве параметра передаю значение из вектора
внутри запущенного потока обрабатываю переменные (сколько обработано, сколько осталось все через InterlockedExchangeAdd)
отображение заключил в EnterCriticalSection/LeaveCriticalSection
но приложение то нормально работает, то просто падает.
P.S. Мозг закипает.
Re[2]: Проблема с потоками
От: SmileIlya  
Дата: 13.07.14 06:12
Оценка: :)
Может я что-то не так описал, для полного понимания вот код:



// запускается из View
CWinThread* thread = AfxBeginThread( 
     CMyDoc::ThreadLoadProcMainThread, 
     (LPVOID)GetDocument());
// Document

UINT CMyDoc::ThreadLoadProcMainThread(LPVOID pParam)
{
    CMyDoc* doc = (CMyDoc*)pParam;
    doc->lCount = doc->m_vData.size();
    g_pDoc = doc; // определен глобально
    if(!doc->m_vData.empty())
    {    
        std::vector<CParamsForCalc*>::iterator it = doc->m_vData.begin();
        for(; it != doc->m_vData.end() ; ++it)
        {
            doc->m_sema->Lock();
            CWinThread* thread = AfxBeginThread(
            CCrPercentDoc::ThreadLoadProcSecondThread, 
            (LPVOID)(*it));
        }
    }
    return 0L;
}


UINT CMyDoc::ThreadLoadProcSecondThread(LPVOID pParam)
{
    CParamsForCalc* pParamsForCalc = (CParamsForCalc*)pParam;
/*
 производится обработка данных (отправляется на сервак)
*/
    ::InterlockedExchangeAdd(&g_pDoc->m_lCountExec,(long)1);
        char szTemp[ 256 ] = "\0";
    sprintf(szTemp, "Обработано %ld осталось %ld", g_pDoc->m_lCountExec, g_pDoc->lCount);

    g_pDoc->m_pChild->SetStatusText( szTemp );
    ::InterlockedExchangeAdd(&g_pDoc->lCount,(long)-1);
    g_pDoc->m_sema->Unlock();
    
    return 0L;
}


в конструкторе документа

m_sema = new CSemaphore(10,10);
::InitializeCriticalSection(&g_cs);


P.S. Самое смешное, что все это нормально работало в 97 студии, при переходе на 2010 начались траблы
Re[3]: Проблема с потоками
От: Carc Россия https://vk.com/gosha_mazov
Дата: 13.07.14 06:55
Оценка: +1
//поскипано
SI> g_pDoc->m_pChild->SetStatusText( szTemp );
//поскипано

SI>P.S. Самое смешное, что все это нормально работало в 97 студии, при переходе на 2010 начались траблы

А вот это вот — выделенное — дяденька, нихарошо!!! Зачем же вы это из рабочего потока хулиганичичиете со строкой состояния в потоке пользовательского интерфейса? (ц)

Не стоит вообще говоря так делать. Имеет смысл вместо SetStatusText (ну ведь явно же вызов к строке состояния) напрямую дергать из рабочего потока. Отошлите лучше сообщение потоку пользовательского интерфейса...

Как-то так:
::SendMessage(hwndOfГлавноОкно_Или_чего_там_за_фрейм, WM_НАШЕ_СООБЩЕНИЕ,0, (LPARAM)(LPCTSTR)szTemp);
//Ну или как Павел выше написал

::PostThreadMessage(hwndOfГлавноОкно_Или_чего_там_за_фрейм, WM_НАШЕ_СООБЩЕНИЕ,0, (LPARAM)(LPCTSTR)szTemp);

Только нужно понимать, что в случае с PostThreadMessage сообщение будет обрабатываться асинхронно. Соответственно тогда нужно в LPARAM пихнуть указатель на строку в куче, ну а обработчик сообщений в главном потоке должен ее освободить потом. Ну и собственно уже обработчик сообщения в пользовательском потоке и дергает SetStatusText с указателем на строку.
Aml Pages Home
Re: Проблема с потоками
От: saf_e  
Дата: 14.07.14 08:34
Оценка: +1
Здравствуйте, SmileIlya, Вы писали:

SI>Доброго всем дня!

SI>Есть проблема с потоками, может я что-то не так делаю или мысли не туда идут.
SI>Есть задача: есть вектор данных ~3500 значений
SI>В программе необходимо запустить обработку этих данных, приложение зависать не должно и пользователь должен видеть сколько записей обработано, сколько осталось.
SI>Небольшой нюанс, есть записи которые обрабатываются продолжительное время.
SI>моя реализация.
SI>Создал семафор[10][10]
SI>запустил || поток (дабы не зависло приложение)
SI>в этом потоке запускаю кол-во потоков согласно семафору(10) в качестве параметра передаю значение из вектора
SI>внутри запущенного потока обрабатываю переменные (сколько обработано, сколько осталось все через InterlockedExchangeAdd)
SI>отображение заключил в EnterCriticalSection/LeaveCriticalSection
SI>но приложение то нормально работает, то просто падает.
SI>P.S. Мозг закипает.

// запускается из View
CWinThread* thread = AfxBeginThread( 
     CMyDoc::ThreadLoadProcMainThread, 
     (LPVOID)GetDocument());
// Document

UINT CMyDoc::ThreadLoadProcMainThread(LPVOID pParam)
{
    CMyDoc* doc = (CMyDoc*)pParam;
    doc->lCount = doc->m_vData.size();


Вот тут явно видно что вы "потенциаьлно" обращаетесь без объекта синхронизации к глобальный данным. Данные лучше передать по копии. Это так, нюанс.

На самом деле больше интересно: а в каком же месте падает? Если еще нет креш-дампера, самое время прикрутить
Re[10]: Проблема с потоками
От: MTimur  
Дата: 14.07.14 09:36
Оценка: -1
Здравствуйте, SmileIlya, Вы писали:

SI>К сожалению это действительно так. Падение не прекратилось.

SI>Каким образом это переделать у меня закончилась фантазия, может будут какие-то предложения?

В данном случае между потоками строку не нужно таскать. Одно сообщение передаст в GUI-поток m_lCountExec (причем, всего один раз при старте ThreadLoadProcMainThread), второе — lCount (после каждого изменения). А строку форматировать и заталкивать в статус-бар или еще куда нужно в потоке GUI'я.
Re[9]: Проблема с потоками
От: Carc Россия https://vk.com/gosha_mazov
Дата: 15.07.14 23:01
Оценка: +1
К>Вообще-то, MFC-шная отправка сообщения и голая WINAPI-шная мало чем отличаются.
К>Просто поменяем шило на мыло.
Еще как отличаются...
Aml Pages Home
Re[4]: Проблема с потоками
От: SmileIlya  
Дата: 13.07.14 08:40
Оценка:
Здравствуйте, Carc, Вы писали:

C>//поскипано

SI>> g_pDoc->m_pChild->SetStatusText( szTemp );
C>//поскипано

CChildFrame::SetStatusText(char* text)
{
SetSendMessage(WM_SET_STATUS_TEXT, 0, (LPARAM)text);
}

падает и с простым SetSendMessage(WM_SET_STATUS_TEXT, 0, (LPARAM)text);
уточню, падает на win7(x86) после обработки ~200-300 записей.

P.S. Сорри за репост, сбойнул инет.
Re[5]: Проблема с потоками
От: Carc Россия https://vk.com/gosha_mazov
Дата: 13.07.14 09:03
Оценка:
Здравствуйте, SmileIlya, Вы писали:

SI>CChildFrame::SetStatusText(char* text)

SI>{
SI> SetSendMessage(WM_SET_STATUS_TEXT, 0, (LPARAM)text);
SI>}

SI>падает и с простым SetSendMessage(WM_SET_STATUS_TEXT, 0, (LPARAM)text);

SI>уточню, падает на win7(x86) после обработки ~200-300 записей.

SI>P.S. Сорри за репост, сбойнул инет.

Нет, я не о том. Из рабочего потока нужно послать сообщение CChildFrame`у со строкой в LPARAM, а уж он пусть зовет SetStatusText. Проблема похоже в том, что пытаемся обратиться в CChildFrame`у из другого (рабочего) потока, нежели которому он принадлежит.
Aml Pages Home
Re[6]: Проблема с потоками
От: SmileIlya  
Дата: 13.07.14 10:08
Оценка:
Здравствуйте, Carc, Вы писали:

C>Нет, я не о том. Из рабочего потока нужно послать сообщение CChildFrame`у со строкой в LPARAM, а уж он пусть зовет SetStatusText. Проблема похоже в том, что пытаемся обратиться в CChildFrame`у из другого (рабочего) потока, нежели которому он принадлежит.


Переделать на простую отправку сообщения CChildFrame не получится это один из базовых классов и менять его нет возможности, но разве критическая секция не подразумевает единоличное владение?
Re: Проблема с потоками
От: rm822 Россия  
Дата: 13.07.14 10:22
Оценка:
Не изобретайте велосипеды


#include "stdafx.h"
#include <stdio.h>
#include <vector>
#include <windows.h>

class MyClass
{
public:
    void DoJob() { Sleep(__rdtsc() % 1000); }
};

void OnProgress(double progress)
{
    printf("%i\n", (int)(progress * 100));
}

int _tmain(int argc, _TCHAR* argv[])
{
    std::vector<MyClass> v;
    for (size_t i = 0; i < 100; ++i)
        v.push_back(MyClass());

    size_t iteration = 0;
    const DWORD mainThread = GetCurrentThreadId();
    #pragma omp parallel for shared(v, iteration) schedule(dynamic, 1) 
    for (ptrdiff_t i = 0; i < static_cast<ptrdiff_t>(v.size()); ++i)
    {
        v[i].DoJob();
        #pragma omp atomic
        iteration += 1;
        
        if (GetCurrentThreadId() == mainThread)
            OnProgress(iteration*1.0 / v.size());
    }
    return 0;
}
Re[7]: Проблема с потоками
От: Carc Россия https://vk.com/gosha_mazov
Дата: 13.07.14 10:26
Оценка:
Здравствуйте, SmileIlya, Вы писали:

SI>Здравствуйте, Carc, Вы писали:


C>>Нет, я не о том. Из рабочего потока нужно послать сообщение CChildFrame`у со строкой в LPARAM, а уж он пусть зовет SetStatusText. Проблема похоже в том, что пытаемся обратиться в CChildFrame`у из другого (рабочего) потока, нежели которому он принадлежит.


SI>Переделать на простую отправку сообщения CChildFrame не получится это один из базовых классов и менять его нет возможности,

Не надо переделывать CChildFrame, переделать надо рабочий поток
Вот тут

UINT CMyDoc::ThreadLoadProcSecondThread(LPVOID pParam)
{
    CParamsForCalc* pParamsForCalc = (CParamsForCalc*)pParam;
/*
 производится обработка данных (отправляется на сервак)
*/
    ::InterlockedExchangeAdd(&g_pDoc->m_lCountExec,(long)1);
        char szTemp[ 256 ] = "\0";
    sprintf(szTemp, "Обработано %ld осталось %ld", g_pDoc->m_lCountExec, g_pDoc->lCount);

    g_pDoc->m_pChild->SetStatusText( szTemp );
//заменить на 
    ::SendMessage(HWND_of_m_pChild,...)
    ::InterlockedExchangeAdd(&g_pDoc->lCount,(long)-1);
    g_pDoc->m_sema->Unlock();
    
    return 0L;
}

Причем HWND лучше получать впрямую через параметры потоковой функции, а не как указатель на CChildFrame.

SI>но разве критическая секция не подразумевает единоличное владение?

Подразумевает. Но это тут вовсе не причем. Обьекты карты сообщений не любят когда с ними работают из другого потока. Поэтому и лучше использовать отправку сообщения.
Aml Pages Home
Re[8]: Проблема с потоками
От: Кодт Россия  
Дата: 13.07.14 23:39
Оценка:
Здравствуйте, Carc, Вы писали:

C>    g_pDoc->m_pChild->SetStatusText( szTemp );
C>//заменить на 
C>    ::SendMessage(HWND_of_m_pChild,...)


Вообще-то, MFC-шная отправка сообщения и голая WINAPI-шная мало чем отличаются.
Просто поменяем шило на мыло.

Но следует заметить, что синхронные сообщения между потоками — это достаточно страшная штука. Можно на ровном месте устроить дедлок.
Вот типичный антипаттерн в двух актах.

Акт первый. "Наивность".
Из рабочего потока посылаем WM_SETTEXT (ну или SetStatusText, который в итоге сведётся к WM_SETTEXT).
Оконный поток об этом не подозревает, параллельно тоже что-то там своё делает, — классическая гонка.
Особенно, если SetStatusText выполняет какую-то ещё полезную работу, кэширует строку, например.

Эврика! Критические секции! (через фьютексы, мьютексы, семафоры, рукодельщину — неважно).

Акт второй. "Тщета".
Оборачиваем всё, что связано со статусом, в критическую секцию.

Рабочий поток входит в секцию.
Рабочий поток отправляет сообщение — и, тем самым, ждёт, когда оконный поток это сообщение возьмёт в цикле прокачки и отработает.
Оконный поток подходит к критической секции и ждёт, когда рабочий поток её отпустит.
Ему бы в этом месте не тупо бездельничать, а прокачать очередь... но кто же знал?

Акт третий. "Искупление". Напишу позже.
Перекуём баги на фичи!
Re[9]: Проблема с потоками
От: SmileIlya  
Дата: 14.07.14 07:00
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Carc, Вы писали:


К>
C>>    g_pDoc->m_pChild->SetStatusText( szTemp );
C>>//заменить на 
C>>    ::SendMessage(HWND_of_m_pChild,...)
К>


К>Вообще-то, MFC-шная отправка сообщения и голая WINAPI-шная мало чем отличаются.

К>Просто поменяем шило на мыло.

К сожалению это действительно так. Падение не прекратилось.
Каким образом это переделать у меня закончилась фантазия, может будут какие-то предложения?
Re[10]: Проблема с потоками
От: stbzh  
Дата: 14.07.14 09:33
Оценка:
Здравствуйте, SmileIlya, Вы писали:
Сорри если пропустил и уже упомянули, но отличие SendMessage от PostMessage в том что первый — синхронный и блокирует основной поток обработки оконного класса (когда ты компилируешь приложение с флагом platform windows, тебе дается этот самый гуишный цикл обработки).
Вообще люди ж уже почти все разжевали здесь. ИМХО, (давать советы дело неблагодарное, но всеж рискну) тебе стоит немного отвлечься на другую задачу, так как создается впечатление что немного зациклился.
И почитать немного корифеев — лично мне в свое время здорово помогли статьи Joseph M. Newcomer. Вот эта, к примеру, по теме: http://www.flounder.com/workerthreads.htm
Re[11]: Проблема с потоками
От: MTimur  
Дата: 14.07.14 09:39
Оценка:
Здравствуйте, MTimur, Вы писали:


MT>В данном случае между потоками строку не нужно таскать. Одно сообщение передаст в GUI-поток m_lTotalCount (причем, всего один раз при старте ThreadLoadProcMainThread), второе — lProcessedCount (после каждого изменения). А строку форматировать и заталкивать в статус-бар или еще куда нужно в потоке GUI'я.

fixed.
Re[12]: Проблема с потоками
От: MTimur  
Дата: 14.07.14 09:53
Оценка:
Здравствуйте, MTimur, Вы писали:

MT>>В данном случае между потоками строку не нужно таскать. Одно сообщение передаст в GUI-поток m_lTotalCount (причем, всего один раз при старте ThreadLoadProcMainThread), второе — lProcessedCount (после каждого изменения). А строку форматировать и заталкивать в статус-бар или еще куда нужно в потоке GUI'я.

MT>fixed.

Посмотрел повнимательнее код. Собственно даже эти данные передавать не нужно, они и так в CMyDoc находятся. Достаточно тупо периодически обновлять текст из основного потока (по таймеру или в ответ на "пустое" сообщение от рабочего потока)
Re[10]: Проблема с потоками
От: Кодт Россия  
Дата: 14.07.14 10:05
Оценка:
Здравствуйте, SmileIlya, Вы писали:

SI>Каким образом это переделать у меня закончилась фантазия, может будут какие-то предложения?


Два способа.

Первый — сделать рабочий поток полностью ведомым объектом.
То есть, пусть у нас есть данные, которые поток перемалывает, и к этим данным несколько функций доступа:
— из процедуры потока, — что-то там молоть
— из откуда угодно, — получить текущий статус (можно в виде строки)
Естественно, публичные данные защищены критической секцией. Важно, что время пребывания в критической секции должно быть детерминированным (никаких ожиданий, никаких синхронных вызовов наподобие того же SendMessage) и коротким. Т.е. рабочий поток не должен зайти в секцию и устроить там числодробилку на несколько секунд: нет, он зашёл, нахватался нужных данных, вышел, и грызёт их сколько влезет; потом зашёл, покидал результаты, вышел.
Процедура потока с какой-то периодичностью посылает совершенно асинхронное сообщение в оконный поток (можно — к конкретному окну): "у меня обновился статус, посмотри".
Окно, когда захочет (может — вообще по таймеру, а не по намёкам от рабочего) лезет в публичные данные, возможно, на несколько микросекунд спотыкается об критическую секцию, берёт, выходит и показывает в окошках.


Второй способ — сделать ведомым оконный поток.
Это более запарно, поскольку у него штатная синхронизация — это очередь оконных сообщений.
Использовать критические секции нельзя, я уже объяснил выше почему. Можно использовать синхрообъекты ядра (тяжёлые мьютексы, семафоры и т.п.), но их ожидание следует делать с помощью MsgWaitForMultipleObjects.
Перекуём баги на фичи!
Re[10]: Проблема с потоками
От: sidorov18 США  
Дата: 14.07.14 11:47
Оценка:
Здравствуйте, SmileIlya, Вы писали:

C>>> g_pDoc->m_pChild->SetStatusText( szTemp );

C>>>//заменить на
C>>> ::SendMessage(HWND_of_m_pChild,...)

SI>К сожалению это действительно так. Падение не прекратилось.

SI>Каким образом это переделать у меня закончилась фантазия, может будут какие-то предложения?

А в каком месте падает?
Код Ваш смахивает на творение новичка в программировании, посему предположу, что Вы могли передать указатель на локальную переменную szTemp. Не Ваш вариант?
Re[3]: Проблема с потоками
От: sidorov18 США  
Дата: 14.07.14 11:58
Оценка:
Здравствуйте, SmileIlya, Вы писали:

doc->>m_sema->Lock();

SI> CWinThread* thread = AfxBeginThread(
SI> CCrPercentDoc::ThreadLoadProcSecondThread,
SI> (LPVOID)(*it));

В качестве оффтопа еще рекомендую для таких задач использовать какую нибудь готовую реализацию пула потоков. Он создаст и оптимальное количество потоков( к примеру — кратное количеству ядер ) и не будет постоянно создавать и завершать потоки в целях оптимизации, как в Вашем случае.
Re: Проблема с потоками
От: AleksandrN Россия  
Дата: 15.07.14 11:16
Оценка:
Здравствуйте, SmileIlya, Вы писали:

SI>P.S. Мозг закипает.


Сделай пул потоков в общей очередью.

Поток, который закончил обрабатывать данные, должен вызвать PostMessage() и отправить сообщение окну, которое отображает данные. Затем поток должен взять из очереди новые данные для обработки. Если данных нет — закрыть семафор для этого потока и ждать, пока он освободится.

После добавления данных в очередь — открыть семафор для потоков, которые ничего не делают.

Для работы с очередью — создать мьютекс. Для приостановки работы потоков, которые ничего не делают — по одному семафору на поток.
Re[10]: Проблема с потоками
От: Кодт Россия  
Дата: 16.07.14 10:47
Оценка:
Здравствуйте, Carc, Вы писали:

К>>Вообще-то, MFC-шная отправка сообщения и голая WINAPI-шная мало чем отличаются.

К>>Просто поменяем шило на мыло.
C>Еще как отличаются...

И в чём отличия, кроме увеличения числа граблей (большее количество объектов, в которые можно выстрелить)?
Перекуём баги на фичи!
Re[11]: Проблема с потоками
От: Carc Россия https://vk.com/gosha_mazov
Дата: 16.07.14 11:04
Оценка:
К>>>Вообще-то, MFC-шная отправка сообщения и голая WINAPI-шная мало чем отличаются.
К>>>Просто поменяем шило на мыло.
C>>Еще как отличаются...

К>И в чём отличия, кроме увеличения числа граблей (большее количество объектов, в которые можно выстрелить)?

MFC как-то очень не любит, когда из соседнего потока пытаются обратиться к CWnd адресуемого картой объектов из гуевого потока. А оно нам надо? Не проще ли передать в рабочий поток параметром до кучки и HWND? И слать сообщение через чистый API. Там — чисто теоретически конечно — можно хотя бы проверить валидность HWND через IsWindow. А с указателем что делать? Есть конечно варианты, IsBadReadPtr — но по уму он выдаст только доступность чтения памяти, а что там в ней мало понятно.

Второе: проблема там в другом. Дело в том, что рабочий поток сам балуется SetStatusText. Т.е. она выполняется в контексте рабочего потока. И соответственно который может быть прерван где-то посередине, и дальше гуевый потом сам начнеть баловать с SetStatusText. По идее если поковыряться, то вроде как там все равно все сведется к отсылке сообщение и можно вроде и забить. Но это все грабли. Не проще ли отослать фрейму сообщение с данными, а он уже разгребая очередь сам обновит данные в строке.

Остальное все нюансы и преждевременные причем. Можно и готовую строку передавать в отсылке сообщения, а формировать строку для статусбара в рабочем потоке. Можно только данные гонять через сообщение (я так понимаю там просто какие числа, которые мы может легко передать как копии через WPARAM\LPARAM). Можно все это синхронно, можно асинхронно. По всякому можно. Но это детали. На 99 из 100 уверен, что проблема в попытке рабочего потока манипулировать напрямую контролами гуевого потока. Плохая практика. Достаточно сказать гуевому потоку, мол измени, а он сам разрулит.
Aml Pages Home
Re[13]: Проблема с потоками
От: Carc Россия https://vk.com/gosha_mazov
Дата: 16.07.14 13:06
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Carc, Вы писали:


C>>Не проще ли отослать фрейму сообщение с данными, а он уже разгребая очередь сам обновит данные в строке.


К>И тут сразу встанет вопрос о сериализации этих данных.

Да ну, какой там вопрос? Вариантов то немного: SendMesage(...., (LPARAM)указатель_на_данные_на_стеке), или PostMessage/PostThreadMessageSendMesage(...., (LPARAM)new (наши_данные)), а гуевый поток уж освободит память. Понятно есть нюансы, может там число и никакие new не нужны, может вообще есть какой-то слева пул\очередь данных Но это уже специфика конкретной задачи и только.

C>>Достаточно сказать гуевому потоку, мол измени, а он сам разрулит.


К>Об том и речь. Пусть гуёвый поток умеет читать и публиковать данные в любой момент времени, а рабочий только сообщает, что пришла пора обновиться.

Дык я про то топикстартеру и толковал. Не нужно мутить критические секции только из-за этого. Рабочий поток чего-то обновил (вот тут вот может и под критической секцией — только толку от нее тут), и дернул гуевый. Гуевый сам все отвизуализирует. Ему по любому лучше знать как и когда отвизуализироваться (ну мало ли там, может быть на 100-ом элементе потом понадобится MessageBox показывать, "Давай бабла, триал закончен" или что-то вроде возможности отменить длительный процесс).
Aml Pages Home
Re[9]: Проблема с потоками
От: WiseAlex Беларусь  
Дата: 19.07.14 22:10
Оценка:
Здравствуйте, Кодт, Вы писали:
К>Акт первый. "Наивность".
К>Из рабочего потока посылаем WM_SETTEXT (ну или SetStatusText, который в итоге сведётся к WM_SETTEXT).
К>Оконный поток об этом не подозревает, параллельно тоже что-то там своё делает, — классическая гонка.
К>Особенно, если SetStatusText выполняет какую-то ещё полезную работу, кэширует строку, например.

Можешь пояснить, если не сложно?
Всегда думал, что оконный поток обрабытавает все сообщения последовательно, получая их из очереди сообщений.
MSDN: Messages sent between threads are processed only when the receiving thread executes message retrieval code.
Как может здесь получится гонка в оконном потоке?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.