Apakah mungkin untuk memodifikasi yang kedua dan mendapatkan hasil yang mirip dengan contoh pertama?
Saat Anda meneruskan variabel atau objek ke Task.Run(()=> DoSomething(index))
Anda menangkap sebuah variabel.
Dalam arti tertentu Anda tidak hanya mengirimkan variabel itu sebagai nilai atau objek, tetapi memberikan thread tersebut akses langsung ke variabel asli. (Ini sangat umum dan memiliki banyak nuansa).
Masalah yang paling mungkin Anda temui adalah CLR mencoba menangkap index
, yang merupakan iterator yang cakupannya tidak dapat meninggalkan batasnya kecuali upaya apa pun untuk melakukannya akan tetap ada di tumpukan (pada dasarnya thread yang sama , sekali lagi terlalu digeneralisasikan).
Ketika CLR 'menangkap' index
ia hanya akan menangkap nilai acak yaitu index
(karena kondisi balapan) - atau nilai terakhir yaitu index
, yaitu double un -intuitif karena Anda secara eksplisit mengatakan bahwa index
tidak boleh sampai ke 9
di baris ini di sini for (var index = 0; index < 9; index++)
.
Inilah hal rumitnya, ketika CLR menangkap index
, ia menangkap berapa pun nilai terakhir untuk index
. Namun setelah loop berakhir index
bertambah sekali lagi menyebabkan 9
menjadi nilai terakhir dari index
.
Hal ini dapat menyebabkan banyak masalah, terutama jika Anda bekerja dengan array, inilah kami IndexOutOfBoundsException
!
Cara memperbaikinya
Cara memperbaikinya sebenarnya sangat sederhana! Cukup buat variabel sementara di loop, dan teruskan variabel tersebut alih-alih index
secara langsung.
Berikut ini contohnya:
void Main()
{
var tasks = new List<Task<int>>();
for (var index = 0; index < 9; index++)
{
int tmpIndex = index;
var task = Task.Run(() => DoSomething(tmpIndex ));
tasks.Add(task);
}
Task.WaitAll(tasks.ToArray());
}
Apakah mungkin untuk memodifikasi yang kedua dan mendapatkan hasil yang mirip dengan contoh pertama?
Catatan Tambahan
jangan pernah mengandalkan data dari tugas untuk disusun secara berurutan, kecuali Anda secara eksplisit menerapkan jaminan bahwa item akan kembali berurutan. TaskScheduler
memilih Tasks
untuk berjalan normal di FIFO(yang pertama masuk pertama keluar), namun, jika TaskScheduler
mengoptimalkan, memprioritaskan, atau mengalihkan tugas (yang sering terjadi) tugas Anda tidak akan selesaikan secara berurutan dan selanjutnya hasil yang Anda peroleh tidak akan berurutan.
person
DekuDesu
schedule
28.05.2021