2013-01-17 28 views
11

Một đồng nghiệp của tôi đã tìm thấy vấn đề với mã của chúng tôi và mất một thời gian để tìm kiếm chính xác những gì đang diễn ra, nhưng nó có thể được chứng minh tốt nhất bằng ví dụ đơn giản này:Viết cho bàn điều khiển bằng cách sử dụng Task.Run() không thành công

// Fails 
class Program 
{ 
    static void Main(string[] args) 
    { 
     Task.Run(() => Console.WriteLine("Hello World")); 
     Console.ReadKey(); 
    } 
} 

// Works fine 
class Program 
{ 
    static void Main(string[] args) 
    { 
     Console.Write(String.Empty); 
     Task.Run(() => Console.WriteLine("Hello World")); 
     Console.ReadKey(); 
    } 
} 

Rõ ràng là việc chơi với bàn điều khiển ở bất cứ nơi nào từ chủ đề chính cũng sẽ cho phép chủ đề nền ghi vào bàn điều khiển, nhưng chúng tôi đang cố gắng hiểu tại sao điều này xảy ra. Bất cứ ai có thể giải thích những gì bằng văn bản cho giao diện điều khiển từ thread chính đạt được rằng đoạn đầu tiên không?

+0

Bạn chưa mô tả những gì xảy ra trong trường hợp lỗi của bạn. Trên hộp của tôi, nó dường như treo cho đến khi bạn nhấn trở lại, tại thời điểm đó nó in. –

+0

@JonSkeet Có đó là hành vi tôi thấy – kevinawalker

Trả lời

4

Tôi có một sự nghi ngờ về những gì đang xảy ra. Những gì tôi đã quan sát:

  • Nếu bạn làm bất cứ điều gì với sản lượng của giao diện điều khiển trước khi bắt đầu ReadKey, không sao đâu. Điều này bao gồm lấy Console.Out nhưng không sử dụng nó
  • Nếu bạn đặt một sự chậm trễ trong để các Console.WriteLine gọi bắt đầu trước Console.ReadKey cuộc gọi, nó là tốt (và bạn có thể có nhiều WriteLine gọi khiReadKey đang chờ

Tôi nghi ngờ rằng hoạt động đầu tiên để sử dụng bảng điều khiển mua một khóa để khởi tạo (để tránh nó được khởi tạo hai lần) và phương pháp ReadKeygiữ cho khóa cho đến khi một khóa đã được đọc. giữ tất cả các chương trình tôi đã chạy cho đến nay.

Các hoạt động thực hiện khởi chạy giả thuyết là thú vị mặc dù - đọc Console.Out "khắc phục" sự cố, nhưng đọc từ Console.In thì không.

Tôi nghi ngờ rằng ReadKey khởi tạo đầu ra vì giá trị vẫn được lặp lại với bàn điều khiển ... nhưng tôi không muốn thề với nó.

Điều thú vị là sử dụng Console.ReadLine() thay vì Console.ReadKey() không gây ra sự cố ngay từ đầu.

+0

Nó chắc chắn là thú vị mà 'Console.ReadLine()' không gây ra cùng một vấn đề. Cảm ơn đã dành thời gian – kevinawalker

4

Thực ra, trường hợp đầu tiên không thành công. "Hello World" xuất hiện ngay trước khi Ứng dụng kết thúc. Đây là một cổ điển Race Condition. Trong trường hợp đầu tiên, Console.ReadKey() từ chuỗi chính đánh bại tác vụ và trong trường hợp thứ hai, tác vụ sẽ thắng. Thật không may, tôi không thể cho bạn biết chính xác lý do tại sao viết chuỗi rỗng làm cho nhiệm vụ giành chiến thắng.

+0

Đây thực sự là giải pháp. –

+0

Tôi không nghĩ rằng điều này là đúng. Nó không giống như các cuộc gọi đến Console.WriteLine xảy ra sau khi cuộc gọi đến Console.ReadLine đã * hoàn thành * - nếu không nếu bạn chờ đợi một thời gian, bạn sẽ thấy đầu ra. Nó dường như là một số loại vấn đề khởi tạo, tôi nghĩ. –

+0

Hoặc để rõ ràng hơn - Tôi tin rằng đó là một điều kiện chủng tộc, nhưng chỉ trong điều kiện của cuộc gọi * bắt đầu * đầu tiên, và chỉ khi 'Console.ReadKey' là cuộc gọi đầu tiên để bàn điều khiển, không ai trong số đó là rõ ràng trong câu trả lời. –

Các vấn đề liên quan