2012-04-16 21 views
15

Kịch bản: Một nhiệm vụ không đồng bộ trong một vòng lặp thực hiện một phương pháp có chứa đối số thay đổi khi chương trình tiếp tục:Chuyển đối số bằng cách thay đổi giá trị thành Tác vụ - Hành vi?

while(this._variable < 100) 
{ 
    this._variable++; 
    var aTask = Task.Factory.StartNew(() => 
    { 
     aList.add(this._variable); 
     update(this._savePoint); 
    }); 
} 

Nếu vòng lặp chạy nhanh hơn so với nhiệm vụ hoàn tất, danh sách sẽ thêm giá trị hiện tại của biến hoặc biến được lưu cục bộ và giá trị ban đầu được thêm vào là gì?

+3

Kiểm tra điều này bởi Jon Skeet: http://csharpindepth.com/Articles/Chapter5/Closures.aspx –

+0

+1 câu hỏi tuyệt vời! – nawfal

Trả lời

11

Đóng cửa đóng trên các biến chứ không phải giá trị. Do đó, việc tăng _variablecó thể thay đổi hành vi của tác vụ đề cập đến nó.

Bạn có thể ngăn chặn điều này bằng cách tạo ra một bản sao cục bộ:

while (this._variable < 100) 
{ 
    this._variable++; 
    int local = _variable; 
    var aTask = Task.Factory.StartNew(() => 
    { 
     aList.add(local); 
     update(this._savePoint); 
    }); 
} 

Hoặc bạn có thể vượt qua các giá trị cho các nhiệm vụ như nhà nước:

while (this._variable < 100) 
{ 
    this._variable++; 
    var aTask = Task.Factory.StartNew(object state => 
    { 
     aList.add((int)state); 
     update(this._savePoint); 
    }, this._variable); 
} 

Những cả công việc bằng cách sao chép giá trị của _variable để một biến tạm thời mới. Trong trường hợp đầu tiên, biến số local được định nghĩa bên trong phạm vi của vòng lặp, do đó bạn sẽ có được một biến mới cho mỗi lần lặp. Trong trường hợp thứ hai, bạn tạo một bản sao giá trị của _variable khi bạn chuyển nó vào Tác vụ làm đối số state. Nếu _variable là loại tham chiếu, các giải pháp này sẽ không hoạt động; bạn phải thực hiện một bản sao.

+0

Điều gì xảy ra nếu biến là một thể hiện của một lớp? 'SomeClass localVariable = this._variable' trong vòng lặp. Là một tham chiếu, làm thế nào bạn sẽ chắc chắn rằng bạn không nhận được một trạng thái thay đổi. – asunrey

+1

@Moyler: bạn sẽ phải sao chép cá thể bên trong vòng lặp, điều đó có nghĩa là bạn tạo một cá thể mới và làm cho các giá trị của các thuộc tính giống hệt với các cá thể của phiên bản gốc. –

+0

Cảm ơn bạn, tôi cần xác nhận đó. Ngoài ra, tôi ban đầu có nghĩa là cho ví dụ của tôi để có một loại tài liệu tham khảo. Tuyệt vời để có được một hai cho một thỏa thuận mặc dù. – asunrey

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