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
변수에 저장됩니다.
GUI 응용 프로그램에서 "정지"또는 "교착 상태"는 거의 항상 프로그램에서 드로잉과 사용자 입력을 모두 처리하는 주 스레드를 차단했다는 의미입니다. 실제로 웹이나 StackOverflow를 검색하는 경우 좋은 해결책과 함께 주제에 대한 기존 토론이 많이 있습니다. –
당신이 구체적으로 말해야하기 때문에 Wait(). Task.WhenAll (생산자, 소비자) .Wait(); 생산자와 소비자에 대한 귀하의 전화를 기다려야한다면 더 나은 UI를 차단하십시오. – DevEstacion
http://stackoverflow.com/questions/19766535/task-waitall-not-working-as-expected – cost