0

I have this code here that starts a process wait 8 seconds and then kill it and again.

for (int i = 0; i < 20; i++)
{
    Process pro = new Process();
    pro.StartInfo.FileName = @"C:\Program Files (x86)\Mozilla Firefox\firefox.exe";
    pro.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;
    pro.Start();

    Thread.Sleep(8000);

    try
    {
        pro.Kill();
        Thread.Sleep(1000);
    }
    catch
    {
        return;
    }
}

As i run the application either on debug mode or direct from the .exe , it successfully starts and kills the process but it is frozen. I cant move its window around or click on other buttons..

Rufus L
  • 36,127
  • 5
  • 30
  • 43
Dionisis
  • 55
  • 1
  • 6
  • 5
    That's because Win forms are single threaded, and a tight loop with no exit leaves no room for the system to repaint your form or respond to mouse events. – Jeremy Mar 31 '15 at 17:33
  • Any solutions to escape from this ? – Dionisis Mar 31 '15 at 17:33
  • You need to do your work asynchronously, not synchronously, in order to not block the UI thread. – Servy Mar 31 '15 at 17:34
  • 3
    @Jeremy Careful, you can *easily* use threads in a win forms app, its just the *UI* thread is a single thread that he is likely blocking. – BradleyDotNET Mar 31 '15 at 17:34
  • I should say single threaded "by default". Bradley is correct – Jeremy Mar 31 '15 at 17:34
  • The easiest solution is to use a timer on an 8 second interval. It is in your VS Toolbox – Jeremy Mar 31 '15 at 17:36
  • "Sleep" means "freeze the application"; this is why you should almost never use "Sleep". It is simply the wrong tool for the job. – Eric Lippert Mar 31 '15 at 17:40

3 Answers3

12

it is frozen. I cant move its window around or click on other buttons.

That's correct. You said to put the thread to sleep.

People seem to have this strange idea that running code when buttons are pressed happens by magic. It does not happen by magic. It happens because the thread runs code that processes the "a button was clicked" message from the operating system. If you put a thread to sleep then it stops processing those messages, because it is asleep.

Putting a thread to sleep is 99% of the time the completely wrong thing to do, so just don't do it.

The right thing to do in C# 5 is to make your method async and then do an await Task.Delay(whatever). Alternatively, create a timer that ticks after some number of seconds. In the tick handling event, turn the timer off and do your logic there.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • 1
    I have a .NET application that runs in background that must perform its operations in the lightest way, with a minimal impact on the system. I have interleaved the resource-consuming calls with `Thread.Sleep(1)` calls. Do you think this is acceptable, or is there a better way to control the resource usage in .NET? – Luca Cremonesi Mar 31 '15 at 19:01
  • 4
    @LucaCremonesi: That is absolutely not the way I would do it, and I have no idea why you'd think that would help you achieve your goal. What are your precise, measurable goals, and what empirical evidence have you collected that this technique achieves your goals? What benefit do you believe that `Sleep(1)` has over, say `Yield`? – Eric Lippert Mar 31 '15 at 20:28
  • 2
    Or, what is wrong simply setting the priority class of the thread lower than average, if you want all other non-idle threads to take precedence? – Eric Lippert Mar 31 '15 at 20:38
  • For compatibility reasons, I must target .NET 2.0 so Yield is not available. The goal is to keep the CPU usage as low as possible (possibly below 5% per core) and to reduce the impact of heavy disk operations. Ideally, setting the priority of the **process** to the lowest value would be effective but, unfortunately, it is not an option. It is actually possible to set the priority of the single thread but I thought that was relative to the other threads of the same process. – Luca Cremonesi Mar 31 '15 at 20:56
  • 3
    @LucaCremonesi: I often hear people say that they want the CPU utilization to be low, and I am genuinely confused by that. I paid good money for that CPU and I want it to be used! If you have a CPU running at 5% capacity all the time then surely you overpaid by a factor of 20. – Eric Lippert Mar 31 '15 at 20:57
  • In general I agree with you, but you have to consider that certain applications, e.g. an antivirus, a background indexing service or an automatic update service, are supposed to run with a minimal impact on the system, since they are not the main "payload". – Luca Cremonesi Mar 31 '15 at 21:05
  • Even if I set the Priority of each thread to Lowest, the documentation states "Operating systems are not required to honor the priority of a thread". Do I have other options in .NET? I could open a new question if you think this subject is relevant to SO and valuable. – Luca Cremonesi Mar 31 '15 at 21:12
  • @LucaCremonesi: I think it is possibly quite a good question, though keep in mind that it is difficult for me or anyone else to make recommendations not knowing what you're actually doing and what your relevant performance metrics are. – Eric Lippert Mar 31 '15 at 21:18
  • If you throttle your calls with `Sleep(1)` you could instead just use a `Timer` with a 1 ms interval. Remember that the interval is relative to your callback and not absolute, i.e. your callbacks won't start overlapping if running takes longer than the interval. Apparently a lot of people think the callback will be called at every fixed interval. That's not the case. It always adds to your callback calling time. – Num Lock Apr 02 '15 at 08:26
  • 1
    @NumLock: Actually the callback of a `System.Threading.Timer` **is** reentrant, so you have to take this in consideration when you implement your method (from the documentation: "The callback can be executed simultaneously on two thread pool threads ..."). – Luca Cremonesi Apr 07 '15 at 15:31
1

Well, my initial guess is that you are doing this all on your UI Thread. Since you make the UI thread sleep, your application will be frozen.

The obvious solution would be doing this in a new thread.

As Servy sais, this is not a great idea. You can use a Timer (https://msdn.microsoft.com/en-us/library/system.timers.timer%28v=vs.110%29.aspx) to do the waiting instead of blocking the UI thread.

Robert
  • 1,658
  • 16
  • 26
  • 2
    Creating a new thread just so that it can sit around doing nothing ~100% of the time is a terrible idea. – Servy Mar 31 '15 at 17:36
  • @Servy What do you suggest? – Dionisis Mar 31 '15 at 17:38
  • 1
    Well doing stuff asynchronously implies you have a new thread, no?Updated my answer, suggesting a Timer. – Robert Mar 31 '15 at 17:42
  • 5
    @Robert: No, asynchrony does NOT imply concurrency. Concurrency is just one kind of asynchrony. If you decide to put toast in the toaster while you are waiting for the eggs to cook, you are using asynchrony. If you decide to hire two cooks, one to cook the eggs and one to cook the toast, you're using both asynchrony and concurrency. Which do you think is cheaper? – Eric Lippert Mar 31 '15 at 17:43
  • 1
    @Robert Here's a slightly longer explanation of that: http://stackoverflow.com/a/17279822/1159478 and here's another: http://stackoverflow.com/questions/23833255/does-using-tasks-tpl-library-make-an-application-multithreaded/23833635#23833635 – Servy Mar 31 '15 at 17:46
  • 1
    I might be on a wrong track here, but I need something (a thread?) that is not my UI thread to do my asynchronous work. I can have one cook to make my eggs, and my toaster, but if I'm the waiter, I won't have time for that. – Robert Mar 31 '15 at 17:47
  • @Robert The amount of time it takes to *start* a new process is basically nothing, at least on a human timescale. Certainly no more work than starting a new thread. – Servy Mar 31 '15 at 17:49
  • Okay, read your article, and dug into msdn (man, that article has so much marketing around the real info...), I see your point now. I always tought the async-await mechanic was like a Background worker. Well, everyone learns something now here and there :) – Robert Mar 31 '15 at 17:55
  • @Servy What are we trying to save here? The cost of one extra thread? Unless this causes a clear performance issue who cares! – Tarik Mar 31 '15 at 18:09
  • @Tarik It's not a huge deal the first time you do it. When your application is doing dozens of things (which all but the most trivial applications will often be doing) it can most certainly begin to matter. It's a scalability issue. Threads are not cheap. It does not take many of them to start causing *significant* problems. – Servy Mar 31 '15 at 18:11
  • @Servy Complexity and scalability are two different things. One of the golden rules in programming is to avoid optimizing early on, as it might not be necessary. For a desktop application, you might want to care about how you affect the server but much less how you affect your local machine. Who cares about the impact of a piece of code that gets executed once per second in comparison with a tight loop of heavy duty calculations. Accordingly, you would win me over by saying that the code is more maintainable, less likely to be buggy but let's forget performance until it becomes relevant. – Tarik Mar 31 '15 at 18:19
  • 1
    @Tarik If every time you ever do long running-non-CPU bound work in your application you always create a new thread that does nothing but sitting around waiting for the operation to finish, you almost certainly won't have a functioning application for anything but toy projects. Advocating practices that are virtually guaranteed to not work in any practical application is simply unproductive, as it will simply require the person to unlearn those unworkable practices as soon as they want to build anything real. – Servy Mar 31 '15 at 18:24
  • Just to save my own skin or what, I wasn't thinking about starting a new thread for every loop, just making a worker thread, and delegating the waiting to that single thread. Of course this wouldn't work with many parallel operations. – Robert Mar 31 '15 at 18:42
  • This article might also help you understand why threads are not a necessary unit of asynchrony. http://blog.stephencleary.com/2013/11/there-is-no-thread.html – Eric Lippert Mar 31 '15 at 20:34
  • I'm more-or-less familiar with this concept, tough I didn't know that c# async-await works this way. Never had to use the async-await mechanism (last time I worked with UI threads, I had a Background Worker, and it was not today actually). I was under the impression that the async-await mechanism is basically just some candy to hide a Thread pool, or something like that. Thanks for the articles, and the advice, it was really useful! – Robert Apr 01 '15 at 09:19
0

The main thread of your application is a loop that constantly peeks messages from Windows message queue. It's like cooperative multi-threading - if you don't update your UI explicitly it won't do that automatically. And it won't because your program (main thread) just spawns a process then sleeps and then kills it (you don't even need that try/catch block - any exception on any thread of your application will terminate it). Sleeping within a thread blocks it. And because you sleep in the main thread (UI) you block the application from peeking from the message queue.

UserControl
  • 14,766
  • 20
  • 100
  • 187