I am creating a thread using
public static void Invoke(ThreadStart method)
{
Thread th = default(Thread);
try
{
th = new Thread(method);
th.Start();
}
catch (Exception ex)
{ }
}
and I am calling it as
Invoke(new Threading.ThreadStart(method_name));
In WPF, I need that what this thread does should not hang UI (i.e. an ASync thread should start). What should I do?
If you are using .net 4.5 you can do
Task.Run( () =>
{
// your code here
});
In .net 4.0 you can do:
Task.Factory.StartNew(() =>
{
// your code here
},
CancellationToken.None,
TaskCreationOptions.DenyChildAttach,
TaskScheduler.Default);
If you are only using the Thread fore responsive UI look at the System.ComponentModel.BackgroundWorker
this is typiccaly used for responsive UI
If you use the latest version of the framwork, you could also look at the async keyword
Async/await vs BackgroundWorker
If you are using WPF, you can Use BeginInvoke. What is exactly wrong with your Code?
This works fine:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace AsyncTest
{
class Program
{
static void Main(string[] args)
{
// First Counter (Thread)
Invoke(new ThreadStart(Do));
Thread.Sleep(10000);
// Second Counter (Thread)
Invoke(new ThreadStart(Do));
Console.ReadLine();
}
public static void Do()
{
for (int i = 0; i < 10000000; i++)
{
Console.WriteLine("Test: " + i.ToString());
Thread.Sleep(100);
}
}
public static void Invoke(ThreadStart ThreadStart)
{
Thread cCurrentThread = null;
try
{
cCurrentThread = new Thread(ThreadStart);
cCurrentThread.Start();
}
catch (Exception ex)
{
}
}
}
}
Related
I read some articles how to corectly cancel a task. Most of them describe: "you have to just add ThrowIfCancellationRequested() inside the method that is long running" - and that's it.
Ok - everything is clear but how to do it properly if we cannot modify method?
Please take a look on "DLL" class. I thought about to get current thread and abort it but that operation
is doesn't recommended by most of programmers. So my question is: how to do it properly?
Little example:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace LongRunningTask
{
static class ClassWithAccess
{
public static void DoHeavyOperation(CancellationToken ct)
{
for (int i = 0; i < 10000000; i++)
{
Thread.Sleep(500);
ct.ThrowIfCancellationRequested();
Console.WriteLine("inside local method that we can modify");
}
}
}
static class DLL
{
public static void DoHeavyOperation()
{
for (int i = 0; i < 10000000; i++)
{
Thread.Sleep(500);
//ct.ThrowIfCancellationRequested(); we can't do this
Console.WriteLine("inside DLL");
}
}
}
class Program
{
static void Main(string[] args)
{
CancellationTokenSource src = new CancellationTokenSource();
CancellationToken ct = src.Token;
Console.WriteLine("start");
Task.Run(() =>
{
//ClassWithAccess.DoHeavyOperation(ct);
DLL.DoHeavyOperation();
}, ct);
Thread.Sleep(3000);
src.Cancel();
Console.WriteLine("Cancel");
Console.ReadKey();
}
}
}
I'm messing around with multithreading and making some sort of task engine. The idea is that the engine can have a configurable amount of threads waiting and when a new task arrives the first free thread picks it up and executes it.
The problem is that something 2 threads pickup the same task somehow. I looked it through and I think that this code should work but obviously it doesn't. If I add the 10ms sleep where it is now commented out it works, but I'm not sure I understand why. It looks like the .Reset() function returns before it actually resets the event?
Can somebody explain? Is there a better way to let only a single thread continue when there are multiple waiting?
Thanks
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace TaskTest
{
public class Engine
{
private ManualResetEvent taskEvent;
private ConcurrentQueue<Task> tasks;
private bool running;
private List<Thread> threads;
private int threadAmount;
private int threadsBusy = 0;
public Engine(int amountOfThreads)
{
taskEvent = new ManualResetEvent(false);
tasks = new ConcurrentQueue<Task>();
threads = new List<Thread>();
threadAmount = amountOfThreads;
}
public void Start()
{
running = true;
for (var i = 0; i < threadAmount; i++)
{
var thread = new Thread(Process);
thread.Name = "Thread " + i;
threads.Add(thread);
thread.Start();
}
}
public void Stop()
{
running = false;
taskEvent.Set();
threads.ForEach(t => t.Join());
}
private void Process()
{
while (running)
{
lock (taskEvent)
{
// Lock it so only a single thread is waiting on the event at the same time
taskEvent.WaitOne();
taskEvent.Reset();
//Thread.Sleep(10);
}
if (!running)
{
taskEvent.Set();
return;
}
threadsBusy += 1;
if (threadsBusy > 1)
Console.WriteLine("Failed");
Task task;
if (tasks.TryDequeue(out task))
task.Execute();
threadsBusy -= 1;
}
}
public void Enqueue(Task t)
{
tasks.Enqueue(t);
taskEvent.Set();
}
}
}
EDIT
Rest of the code:
namespace TaskTest
{
public class Start
{
public static void Main(params string[] args)
{
var engine = new Engine(4);
engine.Start();
while (true)
{
Console.Read();
engine.Enqueue(new Task());
}
}
}
}
namespace TaskTest
{
public class Task
{
public void Execute()
{
Console.WriteLine(Thread.CurrentThread.Name);
}
}
}
When using Console.Read() on a key press, two characters are read from the input. You should use Console.ReadLine() instead.
Note that your code can be simplified a lot by using a BlockingCollection to handle the synchronization:
public class Engine
{
private BlockingCollection<Task> tasks;
private List<Thread> threads;
private int threadAmount;
public Engine(int amountOfThreads)
{
tasks = new BlockingCollection<Task>();
threads = new List<Thread>();
threadAmount = amountOfThreads;
}
public void Start()
{
for (var i = 0; i < threadAmount; i++)
{
var thread = new Thread(Process);
thread.Name = "Thread " + i;
threads.Add(thread);
thread.Start();
}
}
public void Stop()
{
tasks.CompleteAdding();
threads.ForEach(t => t.Join());
}
private void Process()
{
foreach (var task in tasks.GetConsumingEnumerable())
{
task.Execute();
}
}
public void Enqueue(Task t)
{
tasks.Add(t);
}
}
I need the simplest possible Timer to repeat my code infinitely every 5 seconds. No external classes or whatnot.
Just:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Now the following code will be repeated over and over");
//////////////// FOLLOWING CODE /////////////////
/* the repeated code */
//////////////// END OF FOLLOWING CODE /////////////////
}
}
How can I do that?
Use while(true) with Thread.Sleep
using System.Threading;
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Now the following code will be repeated over and over");
while(true)
{
//////////////// FOLLOWING CODE /////////////////
/* the repeated code */
//////////////// END OF FOLLOWING CODE /////////////////
Thread.Sleep(5000);
}
}
}
Simplest form of it :
using System.Threading;
static void Main(string[] args)
{
bool breakConditionFlag = false;
ManualResetEvent waitHandler = new ManualResetEvent(false);
while(breakConditionFlag)
{
//Your Code
waitHandler.WaitOne(TimeSpan.FromMilliseconds(1000)); // 1000 is the Arbitary value you can change it to Suit your purpose;
}
}
Why ManualResetEvent ?
The event makes more efficient use of the processors- you're not having to wake the parent thread up to poll. The kernel will wake you up when the event fires.
Use Timer.
static void Main(string[] args)
{
Timer timer = new System.Threading.Timer((e) =>
{
Console.WriteLine("Now the following code will be repeated over and over");
}, null, 0, (int)TimeSpan.FromSeconds(5).TotalMilliseconds);
Console.Read();
}
Here I have called Console.WriteLine multiple times, you can write your code block instead of it.
You can use Thread.Sleep(5000); But again its also external class according to the OP.
But I would suggest a better solution using Async and Await. One more thing you should have a termination condition, so that you dont produce an infinite call to avoid unnecessary memory consumption.
public static async Task RepeatActionEveryInterval(Action action, TimeSpan interval, CancellationToken cancelToken)
{
while (true)
{
action();
Task task = Task.Delay(interval, cancelToken);
try
{
await task;
}
catch (TaskCanceledException)
{
return;
}
}
}
static void Main(string[] args)
{
CancellationTokenSource cancelToken = new CancellationTokenSource(TimeSpan.FromSeconds(50));
Console.WriteLine("Start");
RepeatActionEveryInterval(() => Console.WriteLine("Repeating Code"), TimeSpan.FromSeconds(5), cancelToken.Token).Wait();
Console.WriteLine("End");
Console.Read();
}
In this example this code will write till 50 seconds.
Use this code for call your function recursively for every 5 seconds.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace recurssiveWithThread
{
class Program
{
static void Main(string[] args)
{
RecWork();
}
public static int i = 0;
public static void RecWork()
{
// Do the things whatever you needed here
i++;
Console.WriteLine(i);
//Thread to make the process to sleep for sometimes
Thread.Sleep(5000);
//Call your function here
RecWork();
}
}
}
Use BackgroundWorker class:
Reference links:
Background worker
If you are using framework >= 4.5.2 QueueBackgroundWorkItem
QueueBackgroundWorkItem
I've gotten this type of thing working in the past with a BackgroundWorker, but I want to use the new async/await approach of .NET 4.5. I may be barking up the wrong tree. Please advise.
Goal: Create a component that will do some long-running work and show a modal form with a progress bar as it's doing the work. The component will get the handle to a window to block interaction while it's executing the long-running work.
Status: See the code below. I thought I was doing well until I tried interacting with the windows. If I leave things alone (i.e. don't touch!), everything runs "perfectly", but if I do so much as click on either window the program hangs after the long-running work ends. Actual interactions (dragging) are ignored as though the UI thread is blocked.
Questions: Can my code be fixed fairly easily? If so, how? Or, should I be using a different approach (e.g. BackgroundWorker)?
Code (Form1 is a standard form with a ProgressBar and a public method, UpdateProgress, that sets the ProgressBar's Value):
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Starting..");
var mgr = new Manager();
mgr.GoAsync();
Console.WriteLine("..Ended");
Console.ReadKey();
}
}
class Manager
{
private static Form1 _progressForm;
public async void GoAsync()
{
var owner = new Win32Window(Process.GetCurrentProcess().MainWindowHandle);
_progressForm = new Form1();
_progressForm.Show(owner);
await Go();
_progressForm.Hide();
}
private async Task<bool> Go()
{
var job = new LongJob();
job.OnProgress += job_OnProgress;
job.Spin();
return true;
}
void job_OnProgress(int percent)
{
_progressForm.UpdateProgress(percent);
}
}
class LongJob
{
public event Progressed OnProgress;
public delegate void Progressed(int percent);
public void Spin()
{
for (var i = 1; i <= 100; i++)
{
Thread.Sleep(25);
if (OnProgress != null)
{
OnProgress(i);
}
}
}
}
class Win32Window : IWin32Window
{
private readonly IntPtr _hwnd;
public Win32Window(IntPtr handle)
{
_hwnd = handle;
}
public IntPtr Handle
{
get
{
return _hwnd;
}
}
}
}
The async and await keywords do not mean "run on a background thread." I have an async/await intro on my blog that describes what they do mean. You must explicitly place CPU-bound operations on a background thread, e.g., Task.Run.
Also, the Task-based Asynchronous Pattern documentation describes the common approaches with async code, e.g., progress reporting.
class Manager
{
private static Form1 _progressForm;
public async Task GoAsync()
{
var owner = new Win32Window(Process.GetCurrentProcess().MainWindowHandle);
_progressForm = new Form1();
_progressForm.Show(owner);
var progress = new Progress<int>(value => _progressForm.UpdateProgress(value));
await Go(progress);
_progressForm.Hide();
}
private Task<bool> Go(IProgress<int> progress)
{
return Task.Run(() =>
{
var job = new LongJob();
job.Spin(progress);
return true;
});
}
}
class LongJob
{
public void Spin(IProgress<int> progress)
{
for (var i = 1; i <= 100; i++)
{
Thread.Sleep(25);
if (progress != null)
{
progress.Report(i);
}
}
}
}
Note that the Progress<T> type properly handles thread marshaling, so there's no need for marshaling within Form1.UpdateProgress.
#StephenCleary's answer is correct. Though, I had to make a little modification to his answer to get the behavior what I think OP wants.
public void GoAsync() //no longer async as it blocks on Appication.Run
{
var owner = new Win32Window(Process.GetCurrentProcess().MainWindowHandle);
_progressForm = new Form1();
var progress = new Progress<int>(value => _progressForm.UpdateProgress(value));
_progressForm.Activated += async (sender, args) =>
{
await Go(progress);
_progressForm.Close();
};
Application.Run(_progressForm);
}
private async void button1_Click(object sender, EventArgs e)
{
IProgress<int> progress = new Progress<int>(value => { progressBar1.Value = value; });
await Task.Run(() =>
{
for (int i = 0; i <= 100; i++)
progress.Report(i);
});
}
Correct me if I'm wrong, but this seems to be the easiest way to update a progress bar.
Is it possible to force the UI thread, to stop waiting for the task(s) to finish, update a UI control via Dispatcher, and then have the UI revert back to waiting for the task(s) to complete?
Ive just tried the following code, but its not working as it appears the
UpdatePB(int NewValue)
method is being executed by the non UI thread.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading.Tasks;
using System.Threading;
using System.Windows.Threading;
using System.Windows.Threading;
namespace UpdateControlViaDispatcherUITaskWaitAll
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void UpdatePB(int NewValue)
{
pb1.Value = NewValue;
}
private void btn1_Click(object sender, EventArgs e)
{
Task tk = Task.Factory.StartNew(() =>
{
Worker();
});
tk.Wait();
}
public void Worker()
{
int currentValue = 0;
for (int i = 0; i < 100; i++)
{
currentValue = i;
Dispatcher.CurrentDispatcher.Invoke(new Action(() =>
{
UpdatePB(currentValue);
}));
Thread.Sleep(1000);
}
}
}
}
Avoid blocking the UI thread:
private void Button_Click(object sender, RoutedEventArgs e)
{
Task.Factory
.StartNew(this.Worker)
.ContinueWith(this.OnWorkerCompleted);
}
public void Worker()
{
Dispatcher.Invoke(new Action(() =>
{
btn1.IsEnabled = false;
}));
// your stuff here...
}
private void OnWorkerCompleted(Task obj)
{
Dispatcher.Invoke(new Action(() =>
{
btn1.IsEnabled = true;
}));
}
Try to minimize calls to Dispatcher and also try using BackgroundWorker which supports automatic syncronization between background thread and UI thread with ProgressChanged and RunWorkerComplete events.
WPF Dispatcher has task queue of DispatcherOperation, so when you call tk.Wait(); it blocks Dispatcher thread until tk finishes. You haven't ability to pause this waiting and resume again, but only cancel DispatcherOperation. But in your case I assume you better disable button (or whole window) and enable it when tk finishes. So you should consider asynchronous waiting for tk to complete.