Seperti judulnya, apakah ada yang setara dengan Process.Start
(memungkinkan Anda menjalankan aplikasi lain atau file batch) yang bisa saya tunggu?
Saya bermain dengan aplikasi konsol kecil dan ini sepertinya tempat yang sempurna untuk menggunakan async dan menunggu tetapi saya tidak dapat menemukan dokumentasi untuk skenario ini.
Apa yang saya pikirkan adalah sesuatu seperti ini:
void async RunCommand()
{
var result = await Process.RunAsync("command to run");
}
c#
async-await
c#-5.0
linkerro
sumber
sumber
Process.Start
adalah async dan OP tampaknya ingin versi sinkron.Jawaban:
Process.Start()
hanya memulai proses, tidak menunggu sampai selesai, jadi tidak masuk akal untuk membuatnyaasync
. Jika Anda masih ingin melakukannya, Anda dapat melakukan sesuatu sepertiawait Task.Run(() => Process.Start(fileName))
.Tapi, jika Anda ingin asynchronous menunggu proses hingga selesai, Anda dapat menggunakan yang
Exited
acara bersama-sama denganTaskCompletionSource
:sumber
process
danprocess.StartInfo
mengubah apa yang terjadi ketika Anda menjalankannya.Start()
. Misalnya, jika Anda memanggil.EnableRaisingEvents = true
sebelum menetapkanStartInfo
properti seperti yang terlihat di sini, semuanya berfungsi seperti yang diharapkan. Jika Anda mengaturnya nanti, misalnya untuk tetap bersama.Exited
, meskipun Anda menyebutnya sebelumnya.Start()
, ia gagal berfungsi dengan benar -.Exited
langsung menyala daripada menunggu Proses untuk benar-benar keluar. Tidak tahu kenapa, hanya kata hati-hati.process.SynchronizingObject
harus diatur ke komponen formulir untuk menghindari metode yang menangani peristiwa (seperti Keluar, OutputDataReceived, ErrorDataReceived) dipanggil pada utas yang terpisah.Process.Start
diTask.Run
. Jalur UNC, misalnya, akan diselesaikan secara serempak. Cuplikan ini dapat memakan waktu hingga 30 detik untuk menyelesaikan:Process.Start(@"\\live.sysinternals.com\whatever")
Inilah pendapat saya, berdasarkan jawaban svick . Itu menambah redirection output, retensi kode keluar, dan penanganan kesalahan sedikit lebih baik (membuang
Process
objek bahkan jika itu tidak dapat dimulai):sumber
async Task<int> RunProcessAsync(string fileName, string args)
. Saya mengadaptasi contoh ini dan memberikan tiga objek satu per satu. Bagaimana saya bisa menunggu acara peningkatan? misalnya. sebelum aplikasi saya berhenti .. terima kasih banyakDispose
nulls event handler, jadi secara teoritis jika Anda meneleponDispose
tetapi menyimpan referensi di sekitar, saya percaya itu akan menjadi kebocoran. Namun, ketika tidak ada lagi referensi keProcess
objek dan mendapat (sampah) dikumpulkan, tidak ada yang menunjuk ke daftar event handler. Jadi dikumpulkan, dan sekarang tidak ada referensi untuk delegasi yang dulu ada dalam daftar, jadi akhirnya mereka mendapatkan sampah yang dikumpulkan.Dispose
membersihkan beberapa sumber daya, tetapi tidak mencegah referensi yang bocor tetapprocess
ada. Bahkan, Anda akan melihat bahwa ituprocess
merujuk pada penangan, tetapiExited
penangan juga memiliki referensiprocess
. Dalam beberapa sistem, referensi melingkar itu akan mencegah pengumpulan sampah, tetapi algoritma yang digunakan dalam. NET masih akan memungkinkan semuanya dibersihkan selama semuanya hidup di "pulau" tanpa referensi luar.Ini pendekatan lain. Konsep serupa dengan jawaban svick dan Ohad tetapi menggunakan metode ekstensi pada
Process
jenisnya.Metode ekstensi:
Contoh use case dalam metode yang mengandung:
sumber
Saya telah membangun kelas untuk memulai proses dan itu tumbuh selama beberapa tahun terakhir karena berbagai persyaratan. Selama penggunaan saya menemukan beberapa masalah dengan kelas Proses dengan membuang dan bahkan membaca ExitCode. Jadi ini semua diperbaiki oleh kelas saya.
Kelas memiliki beberapa kemungkinan, misalnya membaca keluaran, mulai sebagai Admin atau pengguna yang berbeda, menangkap Pengecualian dan juga memulai semua termasuk asinkron ini. Pembatalan. Bagusnya, hasil bacaan juga dimungkinkan selama eksekusi.
sumber
Saya pikir semua yang harus Anda gunakan adalah ini:
Contoh penggunaan:
sumber
CancellationToken
, jika membatalkan itu bukanKill
proses?CancellationToken
dalamWaitForExitAsync
metode ini diperlukan hanya untuk dapat membatalkan menunggu atau mengatur batas waktu. Membunuh suatu proses dapat dilakukan diStartProcessAsync
: `` `coba {menunggu proses. TungguForExitAsync (cancellationToken); } catch (OperationCanceledException) {process.Kill (); } `` `CancellationToken
, membatalkan token harus mengakibatkan pembatalan operasi, bukan untuk membatalkan menunggu. Inilah yang biasanya diharapkan oleh penelepon metode ini. Jika penelepon ingin membatalkan hanya menunggu, dan membiarkan operasi masih berjalan di latar belakang, cukup mudah dilakukan secara eksternal (di sini adalah metode ekstensiAsCancelable
yang melakukan hal itu).Saya benar-benar khawatir tentang pembuangan proses, bagaimana dengan menunggu untuk keluar dari async ?, ini proposal saya (berdasarkan sebelumnya):
Lalu, gunakan seperti ini:
sumber