Apa cara paling sederhana untuk memblokir utas hingga file dibuka kuncinya dan dapat diakses untuk membaca dan mengganti nama? Misalnya, apakah ada WaitOnFile () di suatu tempat di .NET Framework?
Saya memiliki layanan yang menggunakan FileSystemWatcher untuk mencari file yang akan dikirim ke situs FTP, tetapi peristiwa file yang dibuat akan aktif sebelum proses lain selesai menulis file.
Solusi ideal akan memiliki periode waktu tunggu sehingga utas tidak menggantung selamanya sebelum menyerah.
Sunting: Setelah mencoba beberapa solusi di bawah ini, saya akhirnya mengubah sistem sehingga semua file menulis Path.GetTempFileName()
, kemudian melakukan File.Move()
ke lokasi akhir. Begitu FileSystemWatcher
acara dipicu, file itu sudah lengkap.
Jawaban:
Inilah jawaban yang saya berikan untuk pertanyaan terkait :
sumber
Berawal dari jawaban Eric, saya menyertakan beberapa perbaikan untuk membuat kode jauh lebih kompak dan dapat digunakan kembali. Semoga bermanfaat.
sumber
using
menggunakan null, cukup periksa null di dalamusing
blok.fs
tidak boleh null dicatch
blokir? JikaFileStream
konstruktor melempar, variabel tidak akan diberi nilai, dan tidak ada hal lain di dalamtry
yang bisa melemparIOException
. Bagi saya sepertinya tidak apa-apa untuk melakukannyareturn new FileStream(...)
.Berikut adalah kode umum untuk melakukan ini, terlepas dari operasi file itu sendiri. Ini adalah contoh bagaimana menggunakannya:
atau
Anda juga dapat menentukan jumlah percobaan ulang, dan waktu tunggu di antara percobaan ulang.
CATATAN: Sayangnya, kesalahan Win32 yang mendasari (ERROR_SHARING_VIOLATION) tidak terekspos dengan NET, jadi saya telah menambahkan fungsi hack kecil (
IsSharingViolation
) berdasarkan mekanisme refleksi untuk memeriksa ini.sumber
SharingViolationException
. Faktanya, mereka masih bisa, mundur-kompatibel, asalkan diturunkanIOException
. Dan mereka benar-benar harus.Starting with the .NET Framework 4.5, the HResult property's setter is protected, whereas its getter is public. In previous versions of the .NET Framework, both getter and setter are protected.
Saya mengadakan kelas pembantu untuk hal-hal semacam ini. Ini akan berfungsi jika Anda memiliki kendali atas semua yang akan mengakses file. Jika Anda mengharapkan pertengkaran dari banyak hal lain, maka ini sangat tidak berharga.
Ia bekerja menggunakan mutex bernama. Mereka yang ingin mengakses file mencoba untuk mendapatkan kontrol dari mutex bernama, yang berbagi nama file (dengan '\' s berubah menjadi '/' s). Anda dapat menggunakan Open (), yang akan terhenti hingga mutex dapat diakses atau Anda dapat menggunakan TryOpen (TimeSpan), yang mencoba memperoleh mutex selama durasi tertentu dan mengembalikan false jika tidak dapat memperoleh dalam rentang waktu tersebut. Ini kemungkinan besar harus digunakan di dalam blok penggunaan, untuk memastikan bahwa kunci dilepaskan dengan benar, dan aliran (jika terbuka) akan dibuang dengan benar saat objek ini dibuang.
Saya melakukan tes cepat dengan ~ 20 hal untuk melakukan berbagai membaca / menulis file dan tidak melihat adanya korupsi. Jelas ini tidak terlalu maju, tetapi seharusnya berfungsi untuk sebagian besar kasus sederhana.
sumber
Untuk aplikasi khusus ini, mengamati file secara langsung pasti akan menyebabkan bug yang sulit dilacak, terutama ketika ukuran file meningkat. Berikut adalah dua strategi berbeda yang akan berhasil.
Semoga berhasil!
sumber
Salah satu teknik yang saya gunakan beberapa waktu lalu adalah menulis fungsi saya sendiri. Pada dasarnya tangkap pengecualian dan coba lagi menggunakan pengatur waktu yang dapat Anda aktifkan selama durasi tertentu. Jika ada cara yang lebih baik, silakan berbagi.
sumber
Dari MSDN :
FileSystemWatcher Anda dapat dimodifikasi sehingga tidak melakukan pembacaan / penggantian namanya selama acara "OnCreated", melainkan:
sumber
Dalam kebanyakan kasus, pendekatan sederhana seperti yang disarankan @harpo akan berhasil. Anda dapat mengembangkan kode yang lebih canggih menggunakan pendekatan ini:
sumber
Iklan untuk mentransfer file pemicu proses SameNameASTrasferedFile.trg yang dibuat setelah transmisi file selesai.
Kemudian siapkan FileSystemWatcher yang akan mengaktifkan peristiwa hanya pada file * .trg.
sumber
Saya tidak tahu apa yang Anda gunakan untuk menentukan status kunci file, tetapi sesuatu seperti ini seharusnya melakukannya.
sumber
Solusi yang mungkin adalah, menggabungkan pengamat sistem file dengan beberapa polling,
dapatkan Notifikasi untuk setiap Perubahan pada File, dan ketika mendapatkan notifikasi periksa apakah terkunci seperti yang dinyatakan dalam jawaban yang diterima saat ini: https://stackoverflow.com/a/50800/6754146 Kode untuk membuka filestream disalin dari jawaban dan sedikit dimodifikasi:
Dengan cara ini Anda dapat memeriksa file jika terkunci dan mendapatkan pemberitahuan ketika ditutup melalui callback yang ditentukan, dengan cara ini Anda menghindari polling yang terlalu agresif dan hanya melakukan pekerjaan ketika file tersebut mungkin benar-benar ditutup
sumber
Saya melakukannya dengan cara yang sama seperti Gulzar, teruslah mencoba dengan satu putaran.
Sebenarnya saya bahkan tidak peduli dengan pengamat sistem file. Memungut drive jaringan untuk file baru sekali dalam satu menit itu murah.
sumber
Cukup gunakan acara Berubah dengan NotifyFilter NotifyFilters.LastWrite :
sumber
Saya mengalami masalah serupa saat menambahkan lampiran pandangan. "Menggunakan" menyelamatkan hari itu.
sumber
Bagaimana kalau ini sebagai pilihan:
Tentu saja jika ukuran file dialokasikan sebelumnya pada pembuatan, Anda akan mendapatkan positif palsu.
sumber