第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

循環(huán)不會因 Thread 和 CancellationToken 而停止

循環(huán)不會因 Thread 和 CancellationToken 而停止

C#
拉風(fēng)的咖菲貓 2023-08-13 13:55:41
我正在使用異步回調(diào)的 Windows 套接字應(yīng)用程序。如果我使用 Thread 來啟動_StartListening,當(dāng)我調(diào)用時(shí)StopListening,循環(huán)仍然停止在allDone.WaitOne().?但Task版本就可以了。有什么不同?我的代碼是這個的修改版本原始版本有felix-bManualResetEvent提到的競爭條件。我把它改成了,但問題仍然存在。SemaphoreSlim我在調(diào)試模式下嘗試過,即使我不啟動客戶端,if (cancelToken.IsCancellationRequested)在我調(diào)用后似乎也不會遇到斷點(diǎn)。StopListening對不起。我發(fā)現(xiàn)我不小心啟動了兩個socket服務(wù)器。那就是問題所在。?class WinSocketServer:IDisposable? {? ? ? ? public SemaphoreSlim semaphore = new SemaphoreSlim(0);? ? ? ? private CancellationTokenSource cancelSource = new CancellationTokenSource();? ? ? ? public void AcceptCallback(IAsyncResult ar)? ? ? ? {? ? ? ? ? ? semaphore.Release();? ? ? ? ? ? //Do something? ? ? ? }? ? ? ? private void _StartListening(CancellationToken cancelToken)? ? ? ? {? ? ? ? ? ? try? ? ? ? ? ? {? ? ? ? ? ? ? ? while (true)? ? ? ? ? ? ? ? {? ? ? ? ? ? ? ? ? ? if (cancelToken.IsCancellationRequested)? ? ? ? ? ? ? ? ? ? ? ? break;? ? ? ? ? ? ? ? ? ? Console.WriteLine("Waiting for a connection...");? ? ? ? ? ? ? ? ? ? listener.BeginAccept(new AsyncCallback(AcceptCallback),listener);? ? ? ? ? ? ? ? ? ? semaphore.Wait();? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? ? ? catch (Exception e)? ? ? ? ? ? {? ? ? ? ? ? ? ? Console.WriteLine(e.ToString());? ? ? ? ? ? }? ? ? ? ? ? Console.WriteLine("Complete");? ? ? ? }? ? ? ? public void StartListening()? ? ? ? {? ? ? ? ? ? Task.Run(() => _StartListening(cancelSource.Token));//OK? ? ? ? ? ? var t = new Thread(() => _StartListening(cancelSource.Token));? ? ? ? ? ? t.Start();//Can't be stopped by calling StopListening? ? ? ? }? ? ? ? public void StopListening()? ? ? ? {? ? ? ? ? ? listener.Close();? ? ? ? ? ? cancelSource.Cancel();? ? ? ? ? ? semaphore.Release();? ? ? ? }? ? ? ? public void Dispose()? ? ? ? {? ? ? ? ? ? StopListening();? ? ? ? ? ? cancelSource.Dispose();? ? ? ? ? ? semaphore.Dispose();? ? ? ? }? ? }
查看完整描述

1 回答

?
慕哥9229398

TA貢獻(xiàn)1877條經(jīng)驗(yàn) 獲得超6個贊

您的代碼存在競爭條件,可能會導(dǎo)致死鎖(有時(shí))。讓我們將線程命名為“監(jiān)聽器”(運(yùn)行的線程_StartListening)和“控制”(運(yùn)行的線程StopListening):

  1. 偵聽器線程:if (cancelToken.IsCancellationRequested)-> false

  2. 控制線程:cancelSource.Cancel()

  3. 控制線程:allDone.Set()

  4. 偵聽器線程:allDone.Reset()-> 意外重置停止請求!

  5. 監(jiān)聽線程:listener.BeginAccept(...)

  6. 控制線程:stopListening()退出,而監(jiān)聽器繼續(xù)工作!

  7. 偵聽器線程:allDone.WaitOne()-> 死鎖!沒有人會這么做allDone.Set()。

問題在于如何使用該allDone事件,應(yīng)該是相反的:應(yīng)該在它因任何原因退出之前_StartListening執(zhí)行,而應(yīng)該執(zhí)行:allDone.Set()StopListeningallDone.WaitOne()

class WinSocketServer:IDisposable

{

    // I guess this was in your code, necessary to show proper stopping

    private Socket listener = new Socket(......); 


    public ManualResetEvent allDone = new ManualResetEvent(false);

    private CancellationTokenSource cancelSource = new CancellationTokenSource();


    private void _StartListening(CancellationToken cancelToken)

    {

        try

        {

            listener.Listen(...); // I guess 

            allDone.Reset(); // reset once before starting the loop

            while (!cancelToken.IsCancellationRequested)

            {

                Console.WriteLine("Waiting for a connection...");

                listener.BeginAccept(new AsyncCallback(AcceptCallback),listener);

            }

        }

        catch (Exception e)

        {

            Console.WriteLine(e.ToString());

        }


        allDone.Set(); // notify that the listener is exiting

        Console.WriteLine("Complete");

    }

    public void StartListening()

    {

        Task.Run(() => _StartListening(cancelSource.Token));

    }

    public void StopListening()

    {

        // notify the listener it should exit

        cancelSource.Cancel(); 

        // cancel possibly pending BeginAccept

        listener.Close();

        // wait until the listener notifies that it's actually exiting

        allDone.WaitOne();

    }

    public void Dispose()

    {

        StopListening();

        cancelSource.Dispose();

        allDone.Dispose();

    }

}

更新

值得注意的是,listener.BeginAccept直到有新的客戶端連接才會返回。停止監(jiān)聽時(shí),需要關(guān)閉socket( listener.Close())才能強(qiáng)制BeginAccept退出。


線程/任務(wù)行為的差異確實(shí)很奇怪,它可能源于任務(wù)線程是后臺線程,而常規(guī)線程是前臺線程。


查看完整回答
反對 回復(fù) 2023-08-13
  • 1 回答
  • 0 關(guān)注
  • 108 瀏覽

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號