2014-11-07 4 views
0

내 프로듀서 - 소비자 애플리케이션의 경우 버튼을 클릭하여 트리거했습니다. 그러나 그것은 얼 수 있습니다. 프로젝트의 기본 아이디어는 시작 버튼을 클릭 할 때 대기열에있는 얼마나 많은 짝수를 찾는 것입니다. 취소하려면 취소 버튼을 클릭하십시오. 결과를 콘솔에 출력하고 싶습니다. 하지만 둘 다 작동하지 않습니다. 즉 출력이 없음을 의미합니다 (화면에서 비어 있음). 교착 상태 일 수 있습니까? 어쨌든 화면이 얼어 버립니다.왜 내 창문이 얼어서 교착 상태가됩니까?

전체 깨끗한 코드 :

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Threading; 
using System.Threading.Tasks; 
using System.Threading.Tasks.Dataflow; 
using System.Windows.Forms; 
using System.Runtime.InteropServices; 

namespace CancellationTokenStop 
{ 
    public partial class Form1 : Form 
    { 
     public static BufferBlock<int> m_Queue = new BufferBlock<int>(new DataflowBlockOptions { BoundedCapacity = 1000 }); 
     private static int evenNumber; 
     private static CancellationTokenSource cTokenSource; 
     private static CancellationToken cToken; 
     private static Object obj = new object(); 
     [DllImport("kernel32.dll", SetLastError = true)] 
     [return: MarshalAs(UnmanagedType.Bool)] 
     static extern bool AllocConsole(); 
     public Form1() 
     { 
      InitializeComponent(); 
      AllocConsole(); 
     } 

     private void btnCancel_Click(object sender, EventArgs e) 
     { 
      cTokenSource.Cancel(); 
     } 

     private void btnStart_Click(object sender, EventArgs e) 
     { 
      try 
      { 
       cTokenSource = new CancellationTokenSource(); 
       cToken = cTokenSource.Token; 
       var producer = Producer(); 
       var consumer = Consumer(); 

       Task.WhenAll(producer, consumer).Wait(); 
       Report(); 
      } 
      catch (AggregateException ex) 
      { 
       Console.WriteLine(ex.InnerException); 
       Console.Read(); 
      } 
     } 

     static async Task Producer() 
     { 
      for (int i = 0; i < 200; i++) 
      { 
       // Send a value to the consumer and wait for the value to be processed 
       await m_Queue.SendAsync(i); 
      } 
      // Signal the consumer that there will be no more values 
      m_Queue.Complete(); 
     } 

     static async Task Consumer() 
     { 
      try 
      { 
       var executionDataflowBlockOptions = new ExecutionDataflowBlockOptions 
       { 
        MaxDegreeOfParallelism = 4 
       }; 
       var consumerBlock = new ActionBlock<int>(x => 
       { 
        DoWork(x, cToken); 
        if (x % 2 == 0) 
         // Increment the counter in a thread-safe way 
         Interlocked.Increment(ref evenNumber); 

       }, executionDataflowBlockOptions); 

       // Link the buffer to the consumer 
       using (m_Queue.LinkTo(consumerBlock, new DataflowLinkOptions { PropagateCompletion = true })) 
       { 
        // Wait for the consumer to finish. 
        // This method will exit after all the data from the buffer was processed. 
        await consumerBlock.Completion; 
       } 
      } 
      catch (OperationCanceledException ex) 
      { 
       Console.WriteLine(ex.Message); 
       Console.Read(); 
      } 
     } 

     static void DoWork(int x, CancellationToken cToken) 
     { 
      cToken.Register(() => 
      { 
       Console.WriteLine("Stop at "+x); 
      }); 
      Thread.Sleep(100); 
     } 

     public static void Report() 
     { 
      Console.WriteLine("There are {0} even numbers", evenNumber); 
     } 
    } 
} 

생산자 부분은 그냥 BufferBlock에 데이터를 전송, 간단합니다. 소비자 부분은 ActionBlock을 사용하여 복잡하고 취소 토큰을 전달합니다.

예상 결과는 evenNumber 변수에 저장됩니다.

+0

GUI 응용 프로그램에서 "정지"또는 "교착 상태"는 거의 항상 프로그램에서 드로잉과 사용자 입력을 모두 처리하는 주 스레드를 차단했다는 의미입니다. 실제로 웹이나 StackOverflow를 검색하는 경우 좋은 해결책과 함께 주제에 대한 기존 토론이 많이 있습니다. –

+0

당신이 구체적으로 말해야하기 때문에 Wait(). Task.WhenAll (생산자, 소비자) .Wait(); 생산자와 소비자에 대한 귀하의 전화를 기다려야한다면 더 나은 UI를 차단하십시오. – DevEstacion

+0

http://stackoverflow.com/questions/19766535/task-waitall-not-working-as-expected – cost

답변

0

.Wait 버튼을 클릭하여 UI를 차단하는 대신 await해야합니다.

관련 문제