Saya sedang menulis sebuah program dalam C # yang perlu berulang kali mengakses 1 file gambar. Sebagian besar waktu berfungsi, tetapi jika komputer saya berjalan cepat, ia akan mencoba mengakses file sebelum disimpan kembali ke sistem file dan membuat kesalahan: "File digunakan oleh proses lain" .
Saya ingin mencari jalan keluar, tetapi semua Googling saya hanya menghasilkan membuat cek dengan menggunakan penanganan pengecualian. Ini bertentangan dengan agama saya, jadi saya bertanya-tanya apakah ada cara yang lebih baik untuk melakukannya?
Jawaban:
CATATAN yang diperbarui pada solusi ini : Memeriksa
FileAccess.ReadWrite
akan gagal untuk file Read-Only sehingga solusi telah dimodifikasi untuk memeriksaFileAccess.Read
. Meskipun solusi ini berfungsi karena mencoba memeriksaFileAccess.Read
akan gagal jika file memiliki kunci Tulis atau Baca di atasnya, namun, solusi ini tidak akan berfungsi jika file tidak memiliki kunci Tulis atau Baca di dalamnya, yaitu telah dibuka (untuk membaca atau menulis) dengan akses FileShare.Read atau FileShare.Write.ASLI: Saya telah menggunakan kode ini selama beberapa tahun terakhir, dan saya belum punya masalah dengannya.
Pahami keraguan Anda tentang penggunaan pengecualian, tetapi Anda tidak bisa menghindarinya sepanjang waktu:
sumber
public static bool IsLocked(this FileInfo file) {/*...*/}
.Anda dapat menderita dari kondisi ras thread di mana ada contoh-contoh yang terdokumentasi dari ini digunakan sebagai kerentanan keamanan. Jika Anda memeriksa apakah file tersebut tersedia, tetapi kemudian coba dan gunakan, Anda bisa melempar pada titik itu, yang bisa digunakan oleh pengguna jahat untuk memaksa dan mengeksploitasi kode Anda.
Taruhan terbaik Anda adalah try catch / akhirnya yang mencoba untuk mendapatkan file menangani.
sumber
Gunakan ini untuk memeriksa apakah file terkunci:
Untuk alasan kinerja, saya sarankan Anda membaca konten file dalam operasi yang sama. Berikut ini beberapa contohnya:
Cobalah sendiri:
sumber
IOException
, bukan pada umumnyaException
dan kemudian tes pada tipe.IOException
setelah yang umum. Yang umum akan menangkap semua yang lewat dan spesifikIOException
akan selalu kesepian. Tukar saja keduanya.Cukup gunakan pengecualian sebagaimana dimaksud. Terima bahwa file sedang digunakan dan coba lagi, berulang kali hingga tindakan Anda selesai. Ini juga yang paling efisien karena Anda tidak membuang siklus memeriksa keadaan sebelum bertindak.
Gunakan fungsi di bawah ini, misalnya
Metode yang dapat digunakan kembali yang habis setelah 2 detik
sumber
Mungkin Anda bisa menggunakan FileSystemWatcher dan menonton acara yang Diubah.
Saya belum pernah menggunakan ini sendiri, tetapi mungkin layak dicoba. Jika filesystemwatcher ternyata agak berat untuk kasus ini, saya akan mencoba loop coba / tangkap / tidur.
sumber
Anda dapat mengembalikan tugas yang memberi Anda streaming segera setelah tersedia. Ini solusi yang disederhanakan, tetapi ini adalah titik awal yang baik. Itu aman dari utas.
Anda dapat menggunakan aliran ini seperti biasa:
sumber
GetStreamAsync()
?satu-satunya cara saya tahu adalah dengan menggunakan API kunci Win32 eksklusif yang tidak terlalu cepat, tetapi ada contoh.
Kebanyakan orang, untuk solusi sederhana untuk ini, cukup mencoba / menangkap / tidur loop.
sumber
Semoga ini membantu!
sumber
Jawaban yang diterima di atas mengalami masalah di mana jika file telah dibuka untuk menulis dengan mode FileShare.Read atau jika file memiliki atribut Read-Only kode tidak akan berfungsi. Solusi yang dimodifikasi ini berfungsi paling andal, dengan dua hal yang perlu diingat (seperti juga untuk solusi yang diterima):
Ingatlah hal di atas, ini memeriksa apakah file dikunci untuk ditulis atau dikunci untuk mencegah pembacaan :
sumber
Selain bekerja 3-liner dan hanya untuk referensi: Jika Anda ingin full blown - ada sedikit proyek di Microsoft Dev Center:
https://code.msdn.microsoft.com/windowsapps/How-to-know-the-process-704839f4
Dari Pendahuluan:
Ini bekerja dengan menghubungkan ke "Restart Manager Session".
Mungkin sedikit overengineered untuk kebutuhan khusus Anda ... Tetapi jika itu yang Anda inginkan, silakan dan ambil vs-proyek.
sumber
Dalam pengalaman saya, Anda biasanya ingin melakukan ini, kemudian 'melindungi' file Anda untuk melakukan sesuatu yang mewah dan kemudian menggunakan file 'dilindungi'. Jika Anda hanya memiliki satu file yang ingin Anda gunakan seperti ini, Anda dapat menggunakan trik yang dijelaskan dalam jawaban oleh Jeremy Thompson. Namun, jika Anda mencoba melakukan ini pada banyak file (katakanlah, misalnya ketika Anda sedang menulis installer), Anda akan terluka.
Cara yang sangat elegan ini dapat dipecahkan adalah dengan menggunakan fakta bahwa sistem file Anda tidak akan memungkinkan Anda untuk mengubah nama folder jika salah satu file di sana sedang digunakan. Simpan folder dalam sistem file yang sama dan itu akan berfungsi seperti pesona.
Harap dicatat bahwa Anda harus mengetahui cara-cara yang jelas ini dapat dieksploitasi. Lagi pula, file tidak akan dikunci. Perlu diketahui juga bahwa ada alasan lain yang dapat menyebabkan
Move
operasi Anda gagal. Jelas penanganan kesalahan yang tepat (MSDN) dapat membantu di sini.Untuk file individual saya akan tetap dengan saran penguncian diposting oleh Jeremy Thompson.
sumber
FileShare
dan memeriksa kunci.Berikut adalah beberapa kode yang sejauh yang saya tahu terbaik dapat melakukan hal yang sama dengan jawaban yang diterima tetapi dengan kode lebih sedikit:
Namun saya pikir lebih kuat untuk melakukannya dengan cara berikut:
sumber
Anda dapat menggunakan perpustakaan saya untuk mengakses file dari berbagai aplikasi.
Anda dapat menginstalnya dari nuget: Install-Package Xabe.FileLock
Jika Anda ingin informasi lebih lanjut tentang hal ini, periksa https://github.com/tomaszzmuda/Xabe.FileLock
Metode fileLock.Acquire akan mengembalikan true hanya jika dapat mengunci file eksklusif untuk objek ini. Tetapi aplikasi yang mengunggah file juga harus melakukannya dalam kunci file. Jika objek tidak dapat diakses, metod mengembalikan false.
sumber
Saya pernah perlu mengunggah PDF ke arsip cadangan online. Tetapi cadangan akan gagal jika pengguna membuka file di program lain (seperti pembaca PDF). Dengan tergesa-gesa, saya mencoba beberapa jawaban teratas di utas ini tetapi tidak dapat membuatnya bekerja. Apa yang berhasil bagi saya adalah mencoba untuk memindahkan file PDF ke direktori sendiri . Saya menemukan bahwa ini akan gagal jika file dibuka di program lain, dan jika langkah itu berhasil tidak akan ada operasi pemulihan yang diperlukan karena akan ada jika dipindahkan ke direktori yang terpisah. Saya ingin memposting solusi dasar saya jika berguna untuk kasus penggunaan khusus orang lain.
sumber
Saya tertarik untuk melihat apakah ini memicu refleks WTF. Saya memiliki proses yang membuat dan kemudian meluncurkan dokumen PDF dari aplikasi konsol. Namun, saya berurusan dengan kelemahan di mana jika pengguna menjalankan proses beberapa kali, menghasilkan file yang sama tanpa terlebih dahulu menutup file yang dihasilkan sebelumnya, aplikasi akan melempar pengecualian dan mati. Ini adalah kejadian yang agak sering karena nama file didasarkan pada nomor kutipan penjualan.
Alih-alih gagal dengan cara yang tidak berterima, saya memutuskan untuk mengandalkan versi file yang ditambahkan secara otomatis:
Mungkin lebih banyak perhatian dapat diberikan pada
catch
blok untuk memastikan saya menangkap IOException yang benar. Saya mungkin juga akan menghapus penyimpanan aplikasi saat startup karena file-file ini dimaksudkan untuk sementara waktu.Saya menyadari ini melampaui lingkup pertanyaan OP yaitu hanya memeriksa apakah file tersebut digunakan tetapi ini memang masalah yang saya cari untuk diselesaikan ketika saya tiba di sini jadi mungkin itu akan berguna untuk orang lain.
sumber
Apakah sesuatu seperti ini membantu?
sumber
Coba dan pindahkan / salin file ke direktori temp. Jika Anda bisa, itu tidak memiliki kunci dan Anda dapat bekerja dengan aman di direktori temp tanpa mendapatkan kunci. Jika tidak, cobalah untuk memindahkannya lagi dalam x detik.
sumber
Saya menggunakan solusi ini, tetapi saya memiliki rentang waktu antara ketika saya memeriksa penguncian file dengan fungsi IsFileLocked dan ketika saya membuka file. Dalam rentang waktu ini beberapa utas lainnya dapat membuka file, jadi saya akan mendapatkan IOException.
Jadi, saya menambahkan kode tambahan untuk ini. Dalam kasus saya, saya ingin memuat XDocument:
Bagaimana menurut anda? Bisakah saya mengubah sesuatu? Mungkin saya tidak harus menggunakan fungsi IsFileBeingUsed sama sekali?
Terima kasih
sumber