Reputation: 1479
I'm trying to write a .NET console application which sequentially downloads a list of file from web. The program basically works. The problem is that Windows' power-saving sleep mechanism interrupts the downloading. It seems that the SetThreadExecutionState
approach doesn't work in console application?
using System.Runtime.InteropServices;
using System.Net;
public static class Utility {
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern ThreadExecutionState SetThreadExecutionState(ThreadExecutionState esFlags);
[FlagsAttribute]public enum ThreadExecutionState: uint {
CONTINUOUS = 0x80000000,
DISPLAY_REQUIRED = 0x00000002,
SYSTEM_REQUIRED = 0x00000001
}
}
public class MyClass {
void download(string[] urls) {
var i = 0;
Utility.SetThreadExecutionState(Utility.ThreadExecutionState.SYSTEM_REQUIRED);
foreach(var url in urls) {
using(var downloader = new WebClient()) {
var lastTimeProgressMade = DateTime.Now;
downloader.DownloadProgressChanged += (s, e) => { lastTimeProgressMade = DateTime.Now; };
downloader.DownloadFileCompleted += (s, e) => { /* log exception, cancellation or completion... */ };
downloader.DownloadFileAsync(new Uri(url), (++i).ToString());
while(downloader.IsBusy) {
Thread.Sleep(TimeSpan.FromSeconds(15));
if(DateTime.Now - lastTimeProgressMade > TimeSpan.FromMinutes(3)) downloader.CancelAsync();
Console.WriteLine(DateTime.Now);
}
}
}
}
}
Of course the above is simplified code. MyClass
actually contains much more stuff. Anyway, in Main() an instance of MyClass is new'ed and its download() is called. While this program is running, with the keyboard and mouse don't get touched for a certain amount of time, my computer falls into sleep. After waking it up, with the messages I write to console, I can be sure that by the time when Windows was about to sleep the download is in progress. SetThreadExecutionState
doesn't work. What can I do?
Upvotes: 2
Views: 2267
Reputation: 613572
The documentation for SetThreadExecutionState says:
Calling SetThreadExecutionState without ES_CONTINUOUS simply resets the idle timer; to keep the display or system in the working state, the thread must call SetThreadExecutionState periodically.
So, either call it periodically, or include the ES_CONTINUOUS flag. The latter makes more sense, probably. But you should remember to restore the original state when you are done.
Upvotes: 3