2009-10-06 67 views
0

我正試圖在不同的線程中處理套接字,從而導致運行時失敗。請參閱以下代碼。如何在不同的線程中處理相同的套接字?

void MySocket::Lock() 
{ 
    m_LockCount++; 

    if(m_LockCount) 
    { 
     CSocket::Create(8080); 
    } 
} 

void MySocket::Unlock() 
{ 
    m_LockCount--; 

    if(!m_LockCount) 
    { 
     CSocket::Close(); 
    } 
} 

我從一個線程調用Lock()並從另一個線程調用Unlock()。當它執行CSocket :: Close()時,它會發出異常。

我搜索了這個bug並得到了一些原因。 發生這種情況是因爲;一個CSocket對象只能在單個線程的上下文中使用,因爲由CAsyncSocket對象封裝的SOCKET句柄存儲在每個線程句柄映射中。他們還通過在線程之間共享SOCKET句柄來建議解決方案(http://support.microsoft.com/kb/175668)。但在我的情況下,這是不可能的,因爲我除了一些通知回調,這將無法與上述解決方案。任何人都可以建議一種機制來在線程之間共享CSocket而不影響通知回調?

+0

順便說一句,使用++和類似的多線程環境中將不會工作,因爲這些操作不保證是原子的。您可以使用InterlockedIncrement()和InterlockedDecrement()來實現原子性。與您面臨的問題無關,但請記住。 – Naveen 2009-10-06 06:48:48

+0

@Naveen - 感謝提示 – Vadakkumpadath 2009-10-06 10:37:19

回答

1

如你所說,「一個CSocket對象應該只用在單個線程的上下文中」,那麼就沒有「在線程中共享CSocket的機制」。

換句話說,其中一個線程需要擁有CSocket,其他線程不能混淆它。

在這種情況下,解決方案是使用線程間消息傳遞系統。這樣,其他線程中的一個可以向所有者發送信息,說:「嗨,夥計,關閉你的套接字!」

您將如何執行該消息傳遞的細節完全取決於程序的上下文。

3

您coould只需直接使用socket並停止使用,顯然,有缺陷的MFC實現...

+0

我一般同意,但如果這不是一個選項,請參閱我的答案。 – 2009-10-06 06:45:29

1

我會建議你使用一些更高級別的(和bug更少)套接字API像Boost.Asio。請注意,它無論如何都不會使套接字線程安全(請參閱there)。你必須使用一些鎖定/解鎖設施。

我不知道我的理解是關於在不使用通知回調的情況下在線程之間共享套接字的問題。在線程T1和T2之間,假設T1管理一個套接字,T2只有兩種方式才能意識到套接字事件。無論是定期或阻止呼叫,T1發起的某個通知或T2向T1發出的一個問題。

+0

謝謝。我可以添加更多的細節。共享套接字實際上在監聽連接所以T1應該調用CSocket :: Create()並且CSocket將開始監聽。當T2啓動時,它會增加m_LockCount。現在假設T1已經停止。它會減少m_LockCount。之後T2停止。 T2會將m_LockCount遞減爲0,並調用CSocket :: Close()。希望你瞭解我應該分享的方式。 – Vadakkumpadath 2009-10-06 08:02:06

+0

「,因爲由CAsyncSocket對象封裝的SOCKET句柄存儲在每個線程句柄映射中」據此,如果T1退出,則套接字句柄將丟失,因此T2不應該關閉它。 – Gayan 2009-10-06 08:21:25

相關問題