Sharp, да ты что... какой же нонсенс? Винда может прервать выполнение твоего кода на любом этапе, скажем у тебя два потока разделяют общий ресурс, скажем это будет счетчик, каждый из потоков запущены одновременно, и производят одни и те же действия:
- поток читает значение счетчика
- увеличивает его
- записывает данные
Теперь предположим ситуацию, когда винда оборвет один из потоков на стадии когда он еще не успел записать новое значение в счетчик, и передаст управление другому потоку, который начнет выполнятся...
В конце концов и на конец, на выходе обоих потоков получится значение не два, как это можно было бы логически предположить, а единица... Пусть в данном случае программа не вылетит, но неверное значение счетчика явно будет...
А что будет если один поток освободит общий ресурс, в то время как второй продолжит запись/чтение данных с данной области памяти ???
Т.ч. всякие там симафоры и мутексы нельзя списывать со счетов
mov eax, ecx ; номер итема (элемента)
mov ecx,421 ; длина элемента в массиве
mul ecx ; смещение от начала массива
mov edx,[hFirstMem] ; начало массива
add edx,eax ; адрес элемента
test (crNMLVDISPINFO ptr [ebx]).item.iSubItem,-1 ; если запрос первой колонки
jz @F
test edi,LVIF_TEXT ; если запрос текста
jz @@skip
mov eax,(crNMLVDISPINFO ptr [ebx]).item.iSubItem
;----------- text for subitem 0 - File Size ----------
.if eax==1
mov eax,edx
add eax, 128 ; адрес строки с размером файла
;----------- text for subitem 2 - Date & Time --------
.elseif eax==2
mov eax,edx
add eax, 139 ; адрес строки со временем файла
;----------- text for subitem 3 - Attributes ----------
.elseif eax==3
mov eax,edx
add eax, 160 ; адрес строки с аттрибутами файла
;---------- text for subitem 4 - Folder Name ------------
.elseif eax==4
mov eax,edx
add eax, 165 ; адрес строки с директорией файла
.endif
invoke lstrcpy, (crNMLVDISPINFO ptr [ebx]).item.pszText,eax ;копируем данные в буфер структуры
jmp @@skip
@@: ;----- запрос первой колонки -----
test edi,LVIF_TEXT ; если запрос текста
jz short @F
mov eax,edx
push edx
invoke lstrcpy, (crNMLVDISPINFO ptr [ebx]).item.pszText,eax
pop edx
@@:
test edi,LVIF_IMAGE ; если запрос иконки
jz @@skip
;---------------------------------------------------
mov eax,edx ;получаем индекс
add eax,165
push edx
invoke lstrcpy,addr szBuff,eax
pop edx
invoke lstrcat,addr szBuff,edx
invoke SHGetFileInfo,addr szBuff, 0, addr sfi, sizeof SHFILEINFO,\
SHGFI_SYSICONINDEX
mov eax, sfi.iIcon ;системный индекс иконки
@@:
mov (crNMLVDISPINFO ptr [ebx]).item.iImage,eax
@@skip:
;--------------------------------------------------------------------------------------------
.endif
.endif
pop edi
return 0
.else
DefWin:
invoke DefWindowProc, hWin, wmsg, wparam, lparam
ret
.endif
Ret0:
return 0
ListProc endp
;============== ИЗ ЭТОЙ ПРОЦЕДУРЫ ВЫЗЫВАЕТСЯ И ВОЗВРАЩАЕТСЯ НОРМАЛЬНО =============================
ListButtProc proc hWin:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
LOCAL Ps :PAINTSTRUCT
LOCAL Buff[260] :BYTE
LOCAL Count :DWORD
LOCAL ExitCode :DWORD
Switch uMsg
Case WM_MOUSEMOVE
invoke RepaintListButt,hWin,0
;==============================================================================
PrepareIndex proc uses esi lParam:DWORD
LOCAL Buff[256] :byte
LOCAL sfi :SHFILEINFO
LOCAL From:dword, To:dword
@Loop:
mov al,[ebx]
test al,al
jnz @Exist
push esi
add esi,165
invoke lstrcpy,addr Buff,esi
pop esi
invoke lstrcat,addr Buff,esi
invoke SHGetFileInfo,addr Buff, 0, addr sfi, sizeof SHFILEINFO,\
SHGFI_SYSICONINDEX
mov eax,sfi.iIcon
mov [ebx], al
@Exist:
add esi,421
inc From
mov eax,From
inc ebx
cmp eax,To
jl @Loop
; ДО ЭТОГО МЕСТА ДОХОДИТ, ПРИ ЭТОМ ЦИКЛ @Loop ВЫПОЛНЕН ПОЛНОСТЬЮ И ПРАВИЛЬНО.
ret ;ЗДЕСЬ ВЫЛЕТАЕТ ЕСЛИ ВЫЗЫВАТЬ ИЗ ListProc
; ЕСЛИ ВЫЗЫВАТЬ ИЗ ListButtProc ТО ВОЗВРАЩАЕТСЯ НОРМАЛЬНО
Быть может я и не совсем правильно выразился. Официальные источники настоятельно не рекомендуют использовать глобальные переменные, как и обращение к объектам именно из-за отсутствия синхронизации. Первое если не критично, то второе подчас сказывается на программе весьма фатально.
И насчет IDE - отнюдь не всегда потоки работают нормально, так что пинять только на VM не совсем корректно.
Ну и кто-нибудь разъяснит мне ситуацию с Apartment threaded model в ActiveX.Dll ?
> Винда может прервать выполнение твоего кода на любом этапе
Ты хочешь сказать, что если первый поток делает mov eax,1, а второй делает mov eax,2, то после исполнения mov eax,1 я не могу быть уверен, что у меня в eax??? Имхо, ты несколько не прав.
2cresta: при беглом осмотре заметил, что ты не освобождаешь память, выделенную VirtualAlloc. Едва ли, конечно, из за этого, но для полного анализа надо иметь весь исходник, отладчик и пару часов. Из этого у меня есть, увы, только второе.
2LOL: в ActiveX, афаик, мультитреадинг обеспечивается не на уровне приложения, а на уровне системы: т.е. может ли ActiveX-сервер обрабатывать запросы нескольких клиентов сразу. Поэтому все происходит без глюков.
Очень неплохо тема проблемы синхронизации потоков (нитей) разжевана в
книге Эплмана про VB .NET... Там и примерчик реальный имеется, где
показаны ошибки синхронизации и вероятность их происхождения...