Saya melihat di WCF mereka punya [OperationContract(IsOneWay = true)]
atribut. Tapi WCF tampaknya agak lambat dan berat hanya untuk membuat fungsi nonblocking. Idealnya akan ada sesuatu seperti static void nonblocking MethodFoo(){}
, tapi saya rasa itu tidak ada.
Apa cara tercepat untuk membuat panggilan metode nonblocking di C #?
Misalnya
class Foo
{
static void Main()
{
FireAway(); //No callback, just go away
Console.WriteLine("Happens immediately");
}
static void FireAway()
{
System.Threading.Thread.Sleep(5000);
Console.WriteLine("5 seconds later");
}
}
NB : Semua orang yang membaca ini harus memikirkan apakah mereka benar-benar ingin metode ini selesai. (Lihat # 2 jawaban teratas) Jika metode ini harus selesai, maka di beberapa tempat, seperti aplikasi ASP.NET, Anda perlu melakukan sesuatu untuk memblokir dan menjaga utas tetap hidup. Kalau tidak, ini bisa mengarah pada "fire-forget-but-never-sebenarnya-execute", dalam hal ini, tentu saja, akan lebih mudah untuk menulis tanpa kode sama sekali. ( Deskripsi yang baik tentang cara kerjanya di ASP.NET )
sumber
(new Action(FireAway)).BeginInvoke()
Task.Factory.StartNew(() => myevent());
dari jawaban stackoverflow.com/questions/14858261/…Untuk C # 4.0 dan yang lebih baru, menurut saya jawaban terbaik sekarang diberikan di sini oleh Ade Miller: Cara paling sederhana untuk melakukan api dan melupakan metode dalam c # 4.0
sumber
FireAway
?Task.Factory.StartNew(() => FireAway(foo));
.Task.Factory.StartNew(() => FireAway(foo));
foo tidak dapat dimodifikasi dalam loop seperti yang dijelaskan di sini dan di siniUntuk .NET 4.5:
sumber
Task.Factory.StartNew(() => FireAway(), CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
menurut blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspxUntuk menambah jawaban Will , jika ini adalah aplikasi konsol, cukup masukkan a
AutoResetEvent
dan aWaitHandle
untuk mencegahnya keluar sebelum utas pekerja selesai:sumber
WaitOne
selalu memblokir danAutoResetEvent
akan selalu bekerjaWaitHandle
s, masing-masing dengan lariknya sendiriAutoResetEvent
dan yang sesuaiThreadPool.QueueUserWorkItem
. Setelah itu baru sajaWaitHandle.WaitAll(arrayOfWaitHandles)
.Cara mudah adalah membuat dan memulai utas dengan parameter lambda:
Dengan menggunakan metode ini di atas ThreadPool.QueueUserWorkItem Anda dapat memberi nama utas baru Anda agar lebih mudah untuk debugging. Selain itu, jangan lupa untuk menggunakan penanganan kesalahan yang luas dalam rutinitas Anda karena pengecualian yang tidak ditangani di luar debugger akan secara tiba-tiba merusak aplikasi Anda:
sumber
Cara yang disarankan untuk melakukan ini ketika Anda menggunakan Asp.Net dan .Net 4.5.2 adalah dengan menggunakan
QueueBackgroundWorkItem
. Ini adalah kelas pembantu:Contoh penggunaan:
atau menggunakan async:
Ini berfungsi dengan baik di Situs Web Azure.
Referensi: Menggunakan QueueBackgroundWorkItem untuk Menjadwalkan Pekerjaan Latar Belakang dari Aplikasi ASP.NET di .NET 4.5.2
sumber
Memanggil beginInvoke dan tidak menangkap EndInvoke bukanlah pendekatan yang baik. Jawabannya sederhana: Alasan mengapa Anda harus memanggil EndInvoke adalah karena hasil doa (bahkan jika tidak ada nilai balik) harus di-cache oleh .NET hingga EndInvoke dipanggil. Sebagai contoh jika kode yang dipanggil melempar pengecualian maka pengecualian di-cache dalam data doa. Sampai Anda memanggil EndInvoke, ia tetap ada dalam memori. Setelah Anda menelepon EndInvoke, memori dapat dirilis. Untuk kasus khusus ini dimungkinkan memori akan tetap sampai proses dimatikan karena data dikelola secara internal oleh kode doa. Saya kira GC akhirnya akan mengumpulkannya tetapi saya tidak tahu bagaimana GC akan tahu bahwa Anda telah meninggalkan data vs hanya mengambil waktu yang sangat lama untuk mengambilnya. Saya ragu itu. Karenanya kebocoran memori dapat terjadi.
Lebih banyak dapat ditemukan di http://haacked.com/archive/2009/01/09/asynchronous-fire-and-forget-with-lambdas.aspx
sumber
BeginInvoke
mengembalikan objek pembungkus yang memegang referensi, tetapi tidak direferensikan oleh, objek yang menyimpan data hasil nyata, objek pembungkus akan memenuhi syarat untuk finalisasi setelah semua referensi untuk itu ditinggalkan.Hampir 10 tahun kemudian:
Saya akan menambahkan penanganan pengecualian dan masuk ke dalam FireAway
sumber
Pendekatan .NET 2.0 dan kemudian yang paling sederhana adalah menggunakan Asynchnonous Programming Model (mis. BeginInvoke pada delegasi):
sumber
Task.Run()
ada, ini mungkin cara paling ringkas untuk melakukan ini.