2015-04-27 100 views
1

我正在寫一個小應用程序,我想檢查特定的應用程序是否正在運行。我創建了一個窗口,它具有一個ListView子窗口,另一個帶有計時器的子窗口,它的計數爲0.我希望數字檢查,如果進程關閉了,或者監視了,或者時間到了。無論哪種方式窗戶應該關閉。什麼是連續更新ListView的正確方法?

我的問題是,我想創建一個線程,它監視進程,並更新列表視圖。我有一個全局變量ProcArrayCountDisplay,它包含當前正在顯示的多個項目(正在運行)。 因爲我改變這個變量的線程,並監控它,因此該窗口可以關閉,明明什麼是錯的,因爲有時我得到一個Access Violation

我試圖使用的功能InterlockedIncrement(&ProcArrayCountDisplay);InterlockedDecrement(&ProcArrayCountDisplay);,其中結構將被修改,但沒有運氣。

所以我很拙劣地做錯了事。但是我應該怎麼做纔對?有時,Listview會閃爍。我能做些什麼嗎?

在此先感謝!

我的代碼:

// globals 
typedef struct 
{ 
    BOOL bKill; 
}PARAMS, *PPARAMS; 

struct ProcToDisplay 
{ 
    wchar_t * ProcessName; 
    wchar_t * DisplayName; 
}; 
struct ProcToDisplay **ProcArrayDisplay = NULL; 
int ProcArrayCountDisplay = 0; 

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) 
{ 
g_hInst_Main = hInstance; 
int Width, Height, xPos, yPos; 

Width = 400; 
Height = 400; 
xPos = (GetSystemMetrics(SM_CXSCREEN)/2) - (Width/2); 
yPos = (GetSystemMetrics(SM_CYSCREEN)/2) - (Height/2); 

g_hWnd_Main = CreateWindowEx(WS_EX_TOPMOST, WindowClassName, WindowName, WS_OVERLAPPEDWINDOW, xPos, yPos, Width, Height, NULL, NULL, hInstance, NULL); 
if (!g_hWnd_Main) 
{ 
    return FALSE; 
} 

ShowWindow(g_hWnd_Main, nCmdShow); 
UpdateWindow(g_hWnd_Main); 

return TRUE; 
} 

LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
static HBRUSH hbrBackground; 

PAINTSTRUCT ps; 
HDC hdc; 
static unsigned ThreadId; 
static HANDLE hThread = NULL; 
static PARAMS params; 

switch (message) 
{ 
    case WM_CREATE: 
    { 
     INITCOMMONCONTROLSEX iccx; 
     iccx.dwSize = sizeof(INITCOMMONCONTROLSEX); 
     iccx.dwICC = ICC_LISTVIEW_CLASSES; 

     if (!InitCommonControlsEx(&iccx)) 
     { 
      // handle error 
     } 

     g_hWnd_ListView = CreateWindow(WC_LISTVIEW, NULL, WS_BORDER | WS_CHILD | WS_VISIBLE | LVS_REPORT, xStartPos, yStartPos, MaxWidth, MaxHeight, hWnd, NULL, g_hInst_Main, NULL); 
     if (!g_hWnd_ListView) 
     { 
      // handle error 
     } 

     HWND hWnd_Counter = CreateWindow(WindowClassNameChild, NULL, WS_VISIBLE | WS_CHILD | SS_LEFT | WS_BORDER, 10, 370, 380, 17, hWnd, NULL, g_hInst_Main, NULL); 
     if (!hWnd_Counter) 
     { 
      // handle error 
     } 
     SetTimer(hWnd_Counter, 1, 1000, NULL); 

     hThread = (HANDLE)_beginthreadex(NULL, 0, Thread, &params, 0, &ThreadId); 
    } 
    break; 
    case WM_PAINT: 
    { 
     hdc = BeginPaint(hWnd, &ps); 
     EndPaint(hWnd, &ps); 
    } 
    break; 
    case WM_CLOSE: 
    { 
     if (wParam == 1) 
     { 
      DestroyWindow(hWnd); 
     } 
    } 
    break; 
    case WM_DESTROY: 
     params.bKill = TRUE; 
     WaitForSingleObject(hThread, 2000); 
     CloseHandle(hThread); 
     FreeStruct(); 
     PostQuitMessage(0); 
     break; 
    default: 
     return DefWindowProc(hWnd, message, wParam, lParam); 
} 
return 0; 
} 

LRESULT CALLBACK ChildCounterWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
PAINTSTRUCT ps; 
HDC hdc; 

switch (message) 
{ 
    case WM_PAINT: 
    { 
     hdc = BeginPaint(hWnd, &ps); 

     if (ProcArrayCountDisplay == 0) 
     { 
      EndPaint(hWnd, &ps); 
      PostMessage(g_hWnd_Main, WM_CLOSE, 1, 0); 
     } 

     RECT clientRect; 
     GetClientRect(hWnd, &clientRect); 

     //DrawText(hdc, timeString, -1, &clientRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE); 
     ExtTextOut(hdc, 0, 0, TA_LEFT | TA_CENTER | ETO_OPAQUE, &clientRect, timeString, wcslen(timeString), NULL); 

     EndPaint(hWnd, &ps); 
    } 
    break; 
    case WM_TIMER: 
     InvalidateRect(hWnd, NULL, FALSE); 
     break; 
    case WM_DESTROY: 
     // Destroy the timers. 
     KillTimer(hWnd, 1); 
     PostQuitMessage(0); 
     break; 
    default: 
     return DefWindowProc(hWnd, message, wParam, lParam); 
} 

return 0; 
} 

unsigned __stdcall Thread(void *ArgList) 
{ 
PPARAMS pparams; 

pparams = (PPARAMS)ArgList; 

while ((!pparams->bKill) || (ProcArrayCountDisplay > 0)) 
{ 

    // clear previous data 
    ListView_DeleteAllItems(g_hWnd_ListView); 
    FreeStructDisplay(); // frees the array and decrements ProcArrayCountDisplay 


    for (int i = 0; i < ProcArrayCountQuery; i++) 
    { 
     // querys the processes and adds them to the array 
     if (!IsProcessRunning(ProcArrayQuery[ i ]->ProcessName, ProcArrayQuery[ i ]->DisplayName)) 
     { 
      // IsProcessRunning failed 
     } 
    } 

    if (ProcArrayCountDisplay == 0) 
    { 
     // no package to display 
     break; 
    } 

    // display processes 
    InsertListViewItems(); 
    Sleep(1000); 
} 

_endthread(); 

return 0; 
} 
+0

你的閃爍列表視圖是獨一無二的。你是在一個主要的Windows操作系統或他們的嵌入式緊湊線上工作?我已經使用了他們的嵌入式系列,並且Silverlight框架附帶了許多圖形問題(包括許多listview問題)。如果是這樣,那麼就沒有真正的解決辦法,但要停止使用listview,因爲這是所有微軟的實現。 – Javia1492

+0

@ Javia1492:我正在開發一個主要的Windows操作系統。我相信閃爍有一些事情要做,我更新Listview的方式。如果滾動條出現,它會閃爍。 – kampi

回答

0

只能從你描述(線程和訪問衝突)什麼去,你的數據很可能對多個進程(線程)訪問它不受保護。如果屬實,這又可能是您的訪問違規的原因。谷歌critical sectionssemaphoresmutex,(這些鏈接只是一個開始)均具有與實施對於需要過程之間共享數據的線程安全的事情。

下面是使用臨界區的例子(from HERE

這是最簡單的方法,以看到和理解的。你基本上定義一個受保護的邏輯區域只有共享數據才能被編輯。在這個例子中,每次輸入線程處理函數時,邏輯流入關鍵部分,數據被編輯,然後邏輯流出關鍵部分。

DWORD WINAPI ThreadProc(LPVOID lpParameter) 
{ 
    ... 

    // Request ownership of the critical section. 
    EnterCriticalSection(&CriticalSection); 

    // Access the shared resource. 

    // Release ownership of the critical section. 
    LeaveCriticalSection(&CriticalSection); 

    ... 
return 1; 
} 

請參閱以下鏈接提供以上如何創建全局(CriticalSection的),以及如何使用前初始化。

+0

我知道我必須使用它們,我只是不知道如何:(你可能請舉個例子嗎? – kampi

+0

'InterlockedIncrement'與Mutexes和信號燈不一樣嗎? – kampi

+0

我對*** [InterlockedIncrement](https://msdn.microsoft.com/en-us/library/windows/desktop/ms683614%28v=vs.85%29.aspx)***沒有任何經驗。看起來簡而言之,它將執行特定於單個變量的原子增量(32位或64位)邊界。它可能對其他數據類型(如結構或列表類型)沒有用處。 – ryyker

相關問題