I wish there was a File.ExistsAsync()

I have:

bool exists = await Task.Run(() => File.Exists(fileName));

Using a thread for this feels like an antipattern. Is there a cleaner way?

有帮助吗?

解决方案 3

There isn't a File.ExistsAsync probably for good reason; because it makes absolutely no sense to have one; File.Exists is not going to take very long; I tested it as 0.006255ms when the file exists and 0.010925ms when the file does not exist.

There are a few times when it is sensible to call File.Exists; however usually I think the correct solution would be to open the file (thus preventing deletion), catching any exceptions - as there is no guarantee that the file will continue to exist after the call to File.Exists.

When you want to create a new file and not overwrite the old one :

File.Open("fn", FileMode.CreateNew)

For most of the use cases I can think of File.Open() (whether for existing or create new) is going to be better because once the call succeeds you will have a handle to the file and be able to do something with it. Even when using the file's existence as a flag I think I'd still open and close it. The only time I've really used File.Exists is when checking to see if a local HTML file is there before calling the browser so I can show a nice error message when it isn't.

The is no guarantee that something else won't delete the file after File.Exists; so if you did open it after checking with File.Exists the open call could still fail.

In my tests using a FileExists on network drive takes longer than File.Open, File.Exists takes 1.5967ms whereas File.OpenRead takes 0.3927ms)

Maybe if you could expand upon why you're doing this we'd be better able to answer; until then I'd say that you shouldn't do this

其他提示

There is no cleaner way than your solution.

The problems of race conditions aside I believe your solution can be used in some situations. e.g.

I have static file content in many different folders. (in my case cshtml views,script files, css files, for mvc) These files (which do not change much, during application execution) are always checked for in every request to the webserver, due to my application architecture, there are alot more places that files are checked for than in the default mvc application. So much so that file.exists takes up quite a portion of time each request.

so race conditions will generally not happen. The only interesting question for me is performance

starting a task with Task.Factory.StartNew() takes 0.002 ms (source Why so much difference in performance between Thread and Task?)

calling file.exists takes "0.006255ms when the file exists and 0.010925ms when the file does not exist." [Richard Harrison]

so by simple math calling the async File.Exists takes 0.008 ms up to 0.012 ms

in the best case async File.Exists takes 1.2 times as long as File.Exists and in the worst case it takes 1.3 times as long. (in my case most paths that are searched do not exist) so most of the time a File.Exists is mostly close to 0.01 ms

so it is not that much overhead, and you can utilize multiple cores/ harddisk controllers etc. more efficiently. With these calculations you can see that asynchroniously checking for existence of 2 files you will already have a performance increase of 1.6 in the worst case (0.02/ 0.012 )

well i'm just asyning async File.Exists is worth it in specific situations.

caveats of my post: i might have not calculated everything correctly i rounded alot i did not measure performance on a single pc i took performance from other posts i just added the time of File.Exists and Task.Factory.StartNew() (this may be wrong) i disregard alot of sideffects of multithreading

Long time since this thread, but I found it today...

ExistsAsync should definitely be a thing. In fact, in UWP, you have to use Async methods to find out if a file exists, as it could take longer than 50ms (anything that 'could' take longer than 50ms should be async in UWP language).

However, this is not UWP. The reason I need it is to check for folder.exists which if on a network share, remote disk, or idle disk would block the UI. So I can put all the messages like "checking..." but the UI wouldn't update without aysnc (or ViewModel, or timers, etc.)

bool exists = await Task.Run(() => File.Exists(fileName)); works perfectly. In my code, I have both (Exists and ExistsAsync) so that I can run Exists() when running on a non UI thread and don't have to worry about the overhead.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top