2

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?

1
  • 1
    SYSTEM_REQUIRED only resets the idle timer once. You need to OR it with CONTINUOUS. And you need to restore it, save the return value. Commented Jan 12, 2014 at 16:07

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you. I really should wrap those as something like Utility.keepWindowsAwake() to prevent myself from making such a silly mistake again.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.