Bagaimana cara mengembalikan nilai dari utas?
c#
.net
multithreading
Sam
sumber
sumber
lock(value) { value = "Hello world"; }
lebih baik dalam menangani penulisan nilai beberapa utas?value
yang terjadi pada waktu yang sama. Tapi, ya, selalu perhatikan kapan kunci diperlukan.Itu tergantung pada bagaimana Anda ingin membuat utas dan versi .NET yang tersedia:
.NET 2.0+:
A) Anda dapat membuat
Thread
objek secara langsung. Dalam hal ini Anda dapat menggunakan "closure" - mendeklarasikan variabel dan menangkapnya menggunakan lambda-expression:B) Anda dapat menggunakan delegasi dan
IAsyncResult
dan mengembalikan nilai dariEndInvoke()
metode:C) Anda dapat menggunakan
BackgroundWorker
kelas. Dalam hal ini Anda dapat menggunakan variabel yang ditangkap (seperti denganThread
objek) atau menanganiRunWorkerCompleted
peristiwa:.NET 4.0+:
Mulai dengan .NET 4.0 Anda dapat menggunakan Perpustakaan Paralel Tugas dan
Task
kelas untuk memulai utas Anda. Kelas generikTask<TResult>
memungkinkan Anda mendapatkan nilai kembali dariResult
properti:.NET 4.5+:
Dimulai dengan .NET 4.5 Anda juga bisa menggunakan
async
/await
keywords untuk mengembalikan nilai dari tugas secara langsung alih-alih mendapatkanResult
properti:Catatan: metode yang berisi kode di atas harus ditandai dengan
async
kata kunci.Untuk banyak alasan penggunaan Task Parallel Library adalah cara yang lebih disukai untuk bekerja dengan utas.
sumber
Saya akan menggunakan pendekatan BackgroundWorker dan mengembalikan hasilnya ke e.Result.
EDIT:
Ini biasanya terkait dengan WinForms dan WPF, tetapi dapat digunakan oleh semua jenis aplikasi .NET. Berikut kode contoh untuk aplikasi konsol yang menggunakan BackgroundWorker:
Keluaran:
PEMBARUAN 2014
Lihat jawaban @ Roger di bawah.
https://stackoverflow.com/a/24916747/141172
Dia menunjukkan bahwa Anda dapat menggunakan Tugas yang mengembalikan a
Task<T>
, dan periksaTask<T>.Result
.sumber
Utas bukanlah metode - Anda biasanya tidak "mengembalikan" nilai.
Namun, jika Anda mencoba mengambil kembali nilai dari hasil beberapa pemrosesan, Anda memiliki banyak opsi, dua yang utama adalah:
Ini sangat tergantung pada bagaimana Anda membuat utas, dan bagaimana Anda ingin menggunakannya, serta bahasa / kerangka / alat yang Anda gunakan.
sumber
Kelas favorit saya, menjalankan metode apa pun di utas lain hanya dengan 2 baris kode.
pemakaian
Berhati-hatilah karena longFunctionComplete TIDAK akan dijalankan pada thread yang sama seperti starthework.
Untuk metode yang mengambil parameter, Anda selalu dapat menggunakan closure, atau memperluas kelas.
sumber
Berikut adalah contoh sederhana menggunakan delegasi ...
Ada seri hebat tentang threading di Threading di C # .
sumber
Cukup gunakan pendekatan delegasi.
Sekarang buat fungsi Multiply yang akan berfungsi di utas lain:
sumber
Saya menemukan utas ini ketika juga mencoba mendapatkan nilai kembali dari metode yang dijalankan dalam Thread. Saya pikir saya akan memposting solusi saya yang berhasil.
Solusi ini menggunakan kelas untuk menyimpan metode yang akan dijalankan (secara tidak langsung) dan menyimpan nilai yang dikembalikan. Kelas dapat digunakan untuk fungsi apa pun dan jenis pengembalian apa pun. Anda cukup membuat instance objek menggunakan tipe nilai kembalian dan kemudian meneruskan fungsi untuk dipanggil melalui lambda (atau delegasi).
Implementasi C # 3.0
Untuk menggunakan kode ini, Anda dapat menggunakan Lambda (atau delegasi). Berikut contoh penggunaan lambda:
Implementasi VB.NET 2008
Siapa pun yang menggunakan VB.NET 2008 tidak dapat menggunakan lambda dengan metode pengembalian non-nilai. Ini memengaruhi
ThreadedMethod
kelas, jadi kami akanExecuteMethod
mengembalikan nilai fungsinya. Ini tidak menyakiti apapun.sumber
Dengan .NET Framework terbaru, dimungkinkan untuk mengembalikan nilai dari utas terpisah menggunakan Tugas, di mana properti Hasil memblokir utas panggilan hingga tugas selesai:
Untuk detailnya, silakan lihat http://msdn.microsoft.com/en-us/library/dd537613(v=vs.110).aspx
sumber
Utas ThreadStart di C # yang digunakan untuk memulai utas memiliki tipe kembalian 'void'.
Jika Anda ingin mendapatkan 'nilai kembali' dari utas, Anda harus menulis ke lokasi bersama (dengan cara yang aman untuk utas) dan membacanya setelah utas selesai dijalankan.
sumber
Jika Anda tidak ingin menggunakan BackgroundWorker, dan hanya menggunakan Thread biasa, Anda dapat mengaktifkan peristiwa untuk mengembalikan data seperti ini:
sumber
thread1_
bagian di kabel AsyncCompletedEventHandler miliknya . Jika hasil edit saya salah, bantu saya untuk memahami apa yang terjadi di sana.thread1_Thread1Completed +=
karenathread1_Thread1Completed
adalah nama suatu fungsi, jadi Anda tidak dapat meletakkannya di sisi kiri operator penugasan. Sisi kiriThread1Completed +=
digunakan karena itu adalah event, sehingga bisa muncul di sisi kiri operator penugasan untuk menambahkan pengendali event. Lihatpublic event AsyncCompletedEventHandler Thread1Completed;
#region
bagian Anda sebelumnya. Aku melihat. Jujur! :)Untaian tidak benar-benar memiliki nilai balik. Namun, jika Anda membuat delegasi, Anda dapat memanggilnya secara asinkron melalui
BeginInvoke
metode ini. Ini akan menjalankan metode pada thread pool thread. Anda bisa mendapatkan nilai pengembalian apa pun dari seperti panggilan viaEndInvoke
.Contoh:
GetAnswer
akan dieksekusi pada utas kumpulan utas dan ketika selesai Anda dapat mengambil jawabannya melaluiEndInvoke
seperti yang ditunjukkan.sumber
The BackgroundWorker bagus ketika mengembangkan untuk Windows Forms.
Katakanlah Anda ingin lulus kelas sederhana bolak-balik:
Saya menulis kelas pendek yang melakukan hal berikut:
Dari dalam rutinitas utas:
Menambahkan delegasi dapat berguna untuk memposting data Anda langsung kembali ke utas utama, tetapi Anda mungkin perlu menggunakan Panggil jika beberapa item data tidak aman untuk utas.
Untuk mengujinya, buat Aplikasi Konsol kecil, dan letakkan ini di file Program.cs :
Berikut tangkapan layar dari apa yang saya dapatkan dengan ini:
Saya berharap orang lain bisa mengerti apa yang saya coba jelaskan.
Saya menikmati mengerjakan thread dan menggunakan delegasi. Mereka membuat C # sangat menyenangkan.
Lampiran: Untuk VB Coders
Saya ingin melihat apa saja yang terlibat dalam penulisan kode di atas sebagai Aplikasi Konsol VB. Konversi melibatkan beberapa hal yang tidak saya harapkan, jadi saya akan memperbarui utas ini di sini bagi mereka yang ingin tahu cara memasang utas di VB.
sumber
sumber
test(){ Thread.Sleep(5000); /*Highly time demanding process*/ return "Returned from test()";}
. Dalam hal ini utas mandiri tidak akan punya waktu untuk menetapkan nilai baru kereturnValue
variabel. Sebagai upaya terakhir, Anda dapat menyimpan referensi utasvar standaloneThread = new Thread(()=> //...);
dan setelah itu, memulainya dengan cara yang disinkronkanstandaloneThread.Start(); standaloneThread.Join();
. Tapi ini jelas bukan praktik terbaik.Solusi sederhana adalah melewatkan parameter oleh ref ke fungsi yang berjalan di utas dan mengubah nilainya di utas.
Jika Anda tidak dapat mengubah fungsi yang berjalan di tapak, Anda dapat membungkusnya dengan fungsi lain:
sumber
Dapat menggunakan Kode Ini:
sumber
Saya bukan ahli dalam threading, itulah mengapa saya melakukannya seperti ini:
Saya membuat file Pengaturan dan
Di dalam utas baru:
Kemudian saya mengambil nilai itu kapan pun saya membutuhkannya.
sumber