Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - Общий форум

Страница: 1 | 2 |

 

  Вопрос: Многопоточная программа. Добавлено: 11.08.04 08:09  

Автор вопроса:  Kolek | ICQ: 6223500 

Ответить

  Ответы Всего ответов: 24  

Номер ответа: 16
Автор ответа:
 sne



Разработчик Offline Client

ICQ: 233286456 

Вопросов: 34
Ответов: 5445
 Web-сайт: hw.t-k.ru
 Профиль | | #16
Добавлено: 12.08.04 01:58
Sharp, да ты что... какой же нонсенс? Винда может прервать выполнение твоего кода на любом этапе, скажем у тебя два потока разделяют общий ресурс, скажем это будет счетчик, каждый из потоков запущены одновременно, и производят одни и те же действия:
- поток читает значение счетчика
- увеличивает его
- записывает данные

Теперь предположим ситуацию, когда винда оборвет один из потоков на стадии когда он еще не успел записать новое значение в счетчик, и передаст управление другому потоку, который начнет выполнятся...

В конце концов и на конец, на выходе обоих потоков получится значение не два, как это можно было бы логически предположить, а единица... Пусть в данном случае программа не вылетит, но неверное значение счетчика явно будет...

А что будет если один поток освободит общий ресурс, в то время как второй продолжит запись/чтение данных с данной области памяти ???

Т.ч. всякие там симафоры и мутексы нельзя списывать со счетов :)

Ответить

Номер ответа: 17
Автор ответа:
 Chill



ICQ: 554200 

Вопросов: 101
Ответов: 343
 Профиль | | #17 Добавлено: 12.08.04 02:04
Согласен со sne

Ответить

Номер ответа: 18
Автор ответа:
 cresta



Вопросов: 117
Ответов: 1538
 Профиль | | #18 Добавлено: 12.08.04 02:12
>Код в студию!

Вот:

ListProc proc hWin:DWORD, wmsg, wparam, lparam
LOCAL hDC :DWORD
    LOCAL Rct :RECT
    LOCAL Ps :PAINTSTRUCT
    LOCAL sfi :SHFILEINFO
    LOCAL szBuff[260] :BYTE

      .if wmsg == WM_CREATE
       mov eax,hWin
         push hWin
         pop listWnd
         call InitListView
         invoke SendMessage,BrowseWnd,WM_LBUTTONUP,0,0
         Call MemAlloc
      .elseif wmsg == WM_NOTIFY
         push edi
         mov edi, lparam
         mov eax, [edi.NMHDR].hwndFrom
         .if eax == hList
            .if [edi.NMHDR].code == LVN_COLUMNCLICK
             xor ecx,ecx
             lea edx,Sort0
             @ResetDir:
             .if ecx!=[edi.NM_LISTVIEW].iSubItem
             mov dword ptr[edx+ecx*4],-1
             .else
             neg dword ptr[edx+ecx*4]
             m2m SortD,dword ptr[edx+ecx*4]
             .endif
             inc ecx
             cmp ecx,5
             jl @ResetDir
             ;-------------------------------------------------
             mov eax,SortedCol
             cmp eax,-1
             je @F
             mov eax,SortedCol
             .if eax==[edi.NM_LISTVIEW].iSubItem
             push [hFirstMem]
             Call Redirect
             jmp @Update
             .endif
             @@:
                 mov eax, Cnt
                dec eax
            .if [edi.NM_LISTVIEW].iSubItem == 0
                invoke SortArr,[hFirstMem],0,eax,421,0
            .elseif [edi.NM_LISTVIEW].iSubItem == 1
                invoke SortArr,[hFirstMem],0,eax,421,128
            .elseif [edi.NM_LISTVIEW].iSubItem == 2
                invoke SortArr,[hFirstMem],0,eax,421,139
            .elseif [edi.NM_LISTVIEW].iSubItem == 3
                invoke SortArr,[hFirstMem],0,eax,421,160
            .elseif [edi.NM_LISTVIEW].iSubItem == 4
                invoke SortArr,[hFirstMem],0,eax,421,165
            .endif
               
            m2m SortedCol,[edi.NM_LISTVIEW].iSubItem

            @Update:
               invoke InvalidateRect,hList,0,TRUE
               invoke UpdateWindow,hList


            .elseif [edi.NMHDR].code == NM_DBLCLK
                invoke DisplayFileName,0
                

            ;********** ВОТ ТАК НЕ РАБОТАЕТ (НЕ ВОЗВРАЩАЕТСЯ ИЗ Ф-ЦИИ PrepareIndex **
            
            ;.elseif [edi.NMHDR].code == LVN_ODCACHEHINT
            ; mov ebx,lparam
            ; mov eax,(crNMLVCACHEHINT ptr [ebx]).iTo
            ; shl eax,16
            ; mov ecx,(crNMLVCACHEHINT ptr [ebx]).iFrom
            ; mov ax,cx
            ; invoke CreateThread,NULL,NULL,addr PrepareIndex,eax,0,addr hThread
            ;***************************************************************************

            .elseif [edi.NMHDR].code == LVN_GETDISPINFO
            mov ebx,lparam
            mov edi,(crNMLVDISPINFO ptr [ebx]).item.imask
            mov ecx,(crNMLVDISPINFO ptr [ebx]).item.iItem
            cmp (crNMHDR ptr [ebx]).iCode,LVN_GETDISPINFO
            jnz @@skip
    
     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
        
        Case WM_PAINT
         invoke BeginPaint,hWin,ADDR Ps
         push 0
         push eax
         mov eax, hWin
cmp eax,CurrPathWnd
jne @F
push hBackBrushButt
push hBackBrushButt
jmp @CallIt
         @@:
         push hButtFrameBrush1
push hButtFrameBrush1;hBackBrushButt;hBackBrush
        
         @CallIt:
         push hWin
         Call RepaintIt
         invoke EndPaint,hWin,ADDR Ps
        
        Case WM_USER+100
         jmp @EndSearch
        
        Case WM_LBUTTONUP
         invoke GetWindowLong,hWin,GWL_USERDATA
            Switch hWin
                Case BrowseWnd
             mov eax,hThread
             test eax,eax
           jnz @Ret
           call BrowseStartFolder
           test eax,eax
           jz @Ret
           invoke lstrcpy,offset szRoot,offset szFileName
           invoke InvalidateRect,CurrPathWnd,0,TRUE

                Case FastWnd
           mov eax,hThread
             test eax,eax
           jnz @Ret
           mov Sort0,-1
           mov Sort1,-1
                mov Sort2,-1
                mov Sort3,-1
                mov Sort4,-1
                mov SortedCol,-1
           invoke SendMessage,hList,LVM_DELETEALLITEMS,0,0
           invoke GetWindowText,EditWnd,addr Buff,56
           invoke szTrim,ADDR Buff
           invoke lstrcpy,ADDR szAll,ADDR szAsterix
           invoke szLeft,ADDR Buff,ADDR Buff,14
           invoke lstrcat,ADDR szAll,ADDR Buff
           invoke lstrcat,ADDR szAll,ADDR szAsterix
           mov Cnt,0
           mov FolderCount,0
           Call DrawResult
           mov CurrMemAddr,0
           ;---------------------------------
           invoke lstrcpy,ADDR szRoot,ADDR szPath
           invoke szLen,addr szRoot
           test eax,eax
           jz @Ret
           invoke GetTickCount
           mov Timer, eax
                         invoke ReadTheFile_1,ADDR szRoot
        
            ;********** ВОТ ТАК РАБОТАЕТ **********************************************
            
                 mov eax,Cnt
             shl eax,16
             mov ecx,0
             mov ax,cx
             invoke CreateThread,NULL,NULL,addr PrepareIndex,eax,0,addr hThread
            ;***************************************************************************
        

                          invoke SetWindowLong,CloseWnd,GWL_USERDATA,addr szCancel
         invoke InvalidateRect,CloseWnd,0,TRUE
         jmp @Ret
         @EndSearch:
         invoke GetTickCount
         sub eax,Timer
         mov STime,eax
         invoke InvalidateRect,listWnd,0,TRUE
         Call DrawResult
         ;----------------------------------------------
         invoke SendMessage,hList,LVM_SETITEMCOUNT,Cnt,LVSICF_NOINVALIDATEALL
         invoke lstrcpy,offset szRoot,offset szFileName
         invoke InvalidateRect,CurrPathWnd,0,TRUE
        
           Case FolderWnd
           mov eax,hThread
             test eax,eax
           jnz @Ret
           invoke DisplayFileName,1
          
           Case CloseWnd
           mov eax,hThread
           test eax,eax
           jnz @F
           push listWnd
           Call DestroyWindow
           jmp @Exit
           @@:
           invoke GetExitCodeThread,hThread,addr ExitCode
           invoke TerminateThread,hThread,ExitCode
           invoke SetWindowLong,CloseWnd,GWL_USERDATA,addr szCancel
         invoke InvalidateRect,CloseWnd,0,TRUE
          
           Endsw
          

Endsw
    
    
    
    @Exit:
    
    
    invoke DefWindowProc,hWin,uMsg,wParam,lParam

@Ret:
    ret

ListButtProc endp

;==============================================================================
PrepareIndex proc uses esi lParam:DWORD
LOCAL Buff[256] :byte
LOCAL sfi :SHFILEINFO
LOCAL From:dword, To:dword

mov From,0
m2m To,Cnt
mov eax,hIconMem
test eax,eax
jnz @F
invoke VirtualAlloc,NULL,Cnt,MEM_COMMIT,PAGE_READWRITE
mov hIconMem,eax
ret
@@:
mov ebx,From
mov eax,hIconMem
add ebx,eax
mov esi,[hFirstMem]

@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 ТО ВОЗВРАЩАЕТСЯ НОРМАЛЬНО

PrepareIndex endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

Ответить

Номер ответа: 19
Автор ответа:
 LamerOnLine



ICQ: 334781088 

Вопросов: 108
Ответов: 2822
 Профиль | | #19 Добавлено: 12.08.04 08:23
Быть может я и не совсем правильно выразился. Официальные источники настоятельно не рекомендуют использовать глобальные переменные, как и обращение к объектам именно из-за отсутствия синхронизации. Первое если не критично, то второе подчас сказывается на программе весьма фатально.
И насчет IDE - отнюдь не всегда потоки работают нормально, так что пинять только на VM не совсем корректно.
Ну и кто-нибудь разъяснит мне ситуацию с Apartment threaded model в ActiveX.Dll ?

Ответить

Номер ответа: 20
Автор ответа:
 sne



Разработчик Offline Client

ICQ: 233286456 

Вопросов: 34
Ответов: 5445
 Web-сайт: hw.t-k.ru
 Профиль | | #20
Добавлено: 12.08.04 10:50
Что значит из-за отсутствия синхронизации? Ты программер, ты и должен заботиться чтобы потоки не использовали совместно общие ресурсы...

А что за АктивХ ?

Ответить

Номер ответа: 21
Автор ответа:
 Sharp


Лидер форума

ICQ: 216865379 

Вопросов: 106
Ответов: 9979
 Web-сайт: sharpc.livejournal.com
 Профиль | | #21
Добавлено: 12.08.04 20:55
> Винда может прервать выполнение твоего кода на любом этапе
Ты хочешь сказать, что если первый поток делает mov eax,1, а второй делает mov eax,2, то после исполнения mov eax,1 я не могу быть уверен, что у меня в eax??? Имхо, ты несколько не прав.
2cresta: при беглом осмотре заметил, что ты не освобождаешь память, выделенную VirtualAlloc. Едва ли, конечно, из за этого, но для полного анализа надо иметь весь исходник, отладчик и пару часов. Из этого у меня есть, увы, только второе.
2LOL: в ActiveX, афаик, мультитреадинг обеспечивается не на уровне приложения, а на уровне системы: т.е. может ли ActiveX-сервер обрабатывать запросы нескольких клиентов сразу. Поэтому все происходит без глюков.

Ответить

Номер ответа: 22
Автор ответа:
 sne



Разработчик Offline Client

ICQ: 233286456 

Вопросов: 34
Ответов: 5445
 Web-сайт: hw.t-k.ru
 Профиль | | #22
Добавлено: 12.08.04 21:13
> Имхо, ты несколько не прав.
Ты слишком упростил задачу...

proc
push ebx
push esi
push edi

mov eax, MemAdress
inc eax _<_тут поток был прерван и выполнена в точности такая же процедура!
mov MemAdress, eax

pop edi
pop esi
pop ebx

Это всего-лишь пример, много упрощенный, маловероятный и надуманый... не спорю, но ситуацию можно придумать и посложнее!

Ответить

Номер ответа: 23
Автор ответа:
 Павел



Администратор

ICQ: 326066673 

Вопросов: 368
Ответов: 5968
 Web-сайт: www.vbnet.ru
 Профиль | | #23
Добавлено: 12.08.04 22:20
Очень неплохо тема проблемы синхронизации потоков (нитей) разжевана в
книге Эплмана про VB .NET... Там и примерчик реальный имеется, где
показаны ошибки синхронизации и вероятность их происхождения...


Ответить

Номер ответа: 24
Автор ответа:
 Sharp


Лидер форума

ICQ: 216865379 

Вопросов: 106
Ответов: 9979
 Web-сайт: sharpc.livejournal.com
 Профиль | | #24
Добавлено: 12.08.04 22:38
Это популярная тема. Она у всех есть - и у Питрека и у Петзольда и у Рихтера. У Танненбаума так целая теория описывается.

Ответить

Страница: 1 | 2 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам