Trong mã bên dưới, tôi muốn đồng bộ hóa báo cáo kết quả của danh sách tác vụ. Điều này đang làm việc ngay bây giờ bởi vì task.Result khối cho đến khi nhiệm vụ hoàn thành. Tuy nhiên, nhiệm vụ id = 3 mất nhiều thời gian để hoàn thành và chặn tất cả các tác vụ đã hoàn thành khác khỏi báo cáo trạng thái của chúng. Tôi nghĩ rằng tôi có thể làm điều này bằng cách di chuyển báo cáo (Console.Write) vào một lệnh .ContinueWith nhưng tôi không có một chuỗi giao diện người dùng vì vậy làm thế nào để tôi nhận được một TaskScheduler để đồng bộ hóa các tác vụ .ContinueWith?Đồng bộ hóa tác vụ mà không có chuỗi giao diện người dùng
Những gì tôi có bây giờ:
static void Main(string[] args)
{
Console.WriteLine("Starting on {0}", Thread.CurrentThread.ManagedThreadId);
var tasks = new List<Task<int>>();
for (var i = 0; i < 10; i++)
{
var num = i;
var t = Task<int>.Factory.StartNew(() =>
{
if (num == 3)
{
Thread.Sleep(20000);
}
Thread.Sleep(new Random(num).Next(1000, 5000));
Console.WriteLine("Done {0} on {1}", num, Thread.CurrentThread.ManagedThreadId);
return num;
});
tasks.Add(t);
}
foreach (var task in tasks)
{
Console.WriteLine("Completed {0} on {1}", task.Result, Thread.CurrentThread.ManagedThreadId);
}
Console.WriteLine("End of Main");
Console.ReadKey();
}
Tôi muốn chuyển sang này hoặc cái gì đó tương tự nhưng tôi cần những Console.Write ("Đã hoàn thành ...") cho tất cả xảy ra trên cùng một sợi:
static void Main(string[] args)
{
Console.WriteLine("Starting on {0}", Thread.CurrentThread.ManagedThreadId);
for (var i = 0; i < 10; i++)
{
var num = i;
Task<int>.Factory.StartNew(() =>
{
if (num == 3)
{
Thread.Sleep(20000);
}
Thread.Sleep(new Random(num).Next(1000, 10000));
Console.WriteLine("Done {0} on {1}", num, Thread.CurrentThread.ManagedThreadId);
return num;
}).ContinueWith(value =>
{
Console.WriteLine("Completed {0} on {1}", value.Result, Thread.CurrentThread.ManagedThreadId);
}
/* need syncronization context */);
}
Console.WriteLine("End of Main");
Console.ReadKey();
}
- gIẢI PHÁP - Sau khi nhận được một số ý kiến và đọc một số các giải pháp này là giải pháp hoàn chỉnh mà những gì tôi muốn. Mục tiêu ở đây là xử lý các tác vụ chạy dài của severl nhanh nhất có thể và sau đó thực hiện điều gì đó với kết quả của từng tác vụ một tại một thời điểm.
static void Main(string[] args)
{
Console.WriteLine("Starting on {0}", Thread.CurrentThread.ManagedThreadId);
var results = new BlockingCollection<int>();
Task.Factory.StartNew(() =>
{
while (!results.IsCompleted)
{
try
{
var x = results.Take();
Console.WriteLine("Completed {0} on {1}", x, Thread.CurrentThread.ManagedThreadId);
}
catch (InvalidOperationException)
{
}
}
Console.WriteLine("\r\nNo more items to take.");
});
var tasks = new List<Task>();
for (var i = 0; i < 10; i++)
{
var num = i;
var t = Task.Factory.StartNew(() =>
{
if (num == 3)
{
Thread.Sleep(20000);
}
Thread.Sleep(new Random(num).Next(1000, 10000));
Console.WriteLine("Done {0} on {1}", num, Thread.CurrentThread.ManagedThreadId);
results.Add(num);
});
tasks.Add(t);
}
Task.Factory.ContinueWhenAll(tasks.ToArray(), _ => results.CompleteAdding());
Console.WriteLine("End of Main");
Console.ReadKey();
}
tôi giả thread Console là một stand-in cho một GUI (WinForms/WPF). Đó không phải là một ý tưởng hay, sự hiện diện của một Dispatcher/Messageloop tạo nên sự khác biệt lớn. –
Nếu không, hãy nghĩ về ý nghĩa của bạn về "xảy ra trên cùng một chuỗi". Không thể làm điều đó trừ khi chủ đề đó đang bỏ phiếu. –
Tôi cần phải thay đổi nó để chỉ một nhiệm vụ ContinueWith chạy cùng một lúc. Nó không quan trọng nếu họ chạy trên cùng một sợi hay không nhưng tôi không thể có hai trong số họ chạy song song. Trong cuộc sống thực, tôi phần ContinueWith đang viết rất nhiều dữ liệu vào một cơ sở dữ liệu. –