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,你會發現很多關於這個主題的討論,以及很好的解決方案。 – 2014-11-07 01:45:23
那麼,因爲你特別說它應該等待()。 Task.WhenAll(生產者,消費者).Wait();阻止你的用戶界面,更好,如果你應該等待生產者和消費者的呼籲 – DevEstacion 2014-11-07 02:27:11
看看http://stackoverflow.com/questions/19766535/task-waitall-not-working-as-expected – cost 2014-11-07 02:39:39