What is the best way to run a loop infinitely in parallel with the application?
This is what I have tried so far:
The button that actives the loop:
private void ActiveDeactiveTest(object sender, EventArgs e)
{
active = !active;
}
The loop:
bool runTest = false;
bool active = false;
public async void Test()
{
while (runTest)
{
if (active)
{
LblOutput.Text = "before";
await Task.Delay(1000);
LblOutput.Text = "after";
}
else
{
LblOutput.Text = "Idle";
}
}
}
And the form instantiation:
public MainPage()
{
InitializeComponent();
runTest = true;
Test();
}
Fairly new to this so any help would be appreciated
Thanks in advance
I don't think there is the best way to loop infinitely but I will provide some of the options. Idea is to start another thread from your main application thread and leverage the loops, usually while, to manage indefinite looping.
Be careful if you are developing UI application because they are quite sensitive in terms of background work. For example, WPF allow only access to UI elements only to the thread which create them, thread known as Dispatcher. This mean that every background thread which need to update UI elements needs to delegate work to dispatcher thread. This is also the case with android with the difference that Dispatcher thread is called UI thread (WPF Dispatcher Thread, Android UI Thread)
WPF
In WPF, a DispatcherObject can only be accessed by the Dispatcher it is associated with. For example, a background thread cannot update the contents of a Button that is associated with the Dispatcher on the UI thread. In order for the background thread to access the Content property of the Button, the background thread must delegate the work to the Dispatcher associated with the UI thread. This is accomplished by using either Invoke or BeginInvoke. Invoke is synchronous and BeginInvoke is asynchronous. The operation is added to the queue of the Dispatcher at the specified DispatcherPriority.
Android
The Android UI toolkit is not thread-safe. So, you must not manipulate your UI from a worker thread—you must do all manipulation to your user interface from the UI thread. Thus, there are simply two rules to Android's single thread model:
Do not block the UI thread
Do not access the Android UI toolkit from outside the UI thread
I will provide few examples just as a show case:
//Option A, common one, loop doesn't need to have iteration at all
Task.Factory.StartNew(() =>
{
while (shouldLooping)
{
//do your job
}
});
//Option B, kind of wierd, loop will have at least one iteration
Task.Factory.StartNew(() =>
{
do
{
//do your job
} while (shouldLooping);
});
//Option C, if you are driven by producer/consumer pattern, BlockingCollection should be shared between producer and consumer
Task.Factory.StartNew(() =>
{
foreach (var item in blockingCollection.GetConsumingEnumerable())
{
Console.WriteLine(item);
}
});
Related
I have a worker thread which calculates data for DataGrid after every change user have made. In some cases user make changes too fast so on GUI thread i call
Thread.Abort();
in the meantime on the worker thread i use such a construction
while (true)
{
try
{
_calculateEvent.WaitOne();
...
Application.Current.MainWindow.Dispatcher.BeginInvoke((Action)delegate()
{
_viewModel.UpdateInterfaceFromAssigningInfo(assigningInfo);
});
}
catch (ThreadAbortException)
{
Thread.ResetAbort();
}
}
Don't know if it will work at all, but for now my main problem is i can't call code on the GUI thread to update interface. At Invoke row i have exception: InvalidOperationException with message
The calling thread cannot access this object because a different
thread owns it.
I'm usually use slightly different way:
Application.Current.MainWindow.Dispatcher.BeginInvoke(new Action( ()=>
{
_viewModel.UpdateInterfaceFromAssigningInfo(assigningInfo);
}));
Try, may be it's a reason.
After some researches i have found info that accurately fills my needs, because in my case i need to update UI only after all calculation in Task have been done.
Option 1.
For the case of WPF application we can benefit from synchronization context task scheduler which runs task right on GUI thread. So, one can employ such scenario to update GUI after task has finished:
Task t = Task.Run(() => foo());
t.ContinueWith((task) =>
{
// Update observable properties
}, TaskScheduler.FromCurrentSynchronizationContext());
Continuation task will be executed on GUI thread and so will be able to update GUI.
Option 2
private async void DownloadFileButton_Click(object sender, EventArgs e)
{
// Since we asynchronously wait, the UI thread is not blocked by our code.
await foo();
// Since we resume on the UI context, we can directly access UI elements.
UpdateObservableProperties();
}
I have a windows form with a datagridview and some buttons. One of the buttons when clicked will call a method called loadMyData() that reads some data from a csv and puts them in three datagridviews in the form.
The code is something like this:
public partial class NewForm : Form
{
private void loadData_Click_1(object sender, EventArgs e) // load market data, create a base copy and update gridview
{
ThreadStart thread1Start = new ThreadStart(loadMyData);
Thread t1 = new Thread(thread1Start);
t1.Start();
}
public void loadMyData()
{
dataMap = dataLoader.newLoadTheData(dataMap, grid1, grid2)
}
}
where dataLoader.newLoadTheData is a static method that takes as input my datagridviews (grid1, grid2) and a dictionary (dataMap). The method simply reads some data from a csv and put the numbers in the 2 datagridviews. These are updated from this method and an updated dictionary (dataMap) is also returned by the method. It all works fine when the method loadMyData() is executed normally but I get this error when I execute it as thread:
Cross-thread operation not valid: Control 'grid1' accessed from a
thread other than the thread it was created on.
I realize that I might be using something like "invoke" but I really can't find a clear example that shows how to do this in my case. Can anyone help with tjis situation? How should I change the code to make it work?
When working with your grid from the other thread, you should do something like this:
if (grid1.InvokeRequired)
grid1.Invoke(new Action(() => { /*do my stuff here*/ })
else
{
/*do my stuff here*/
}
You have to marshal the call back to the UI thread.
Are you using WinForms or WPF?
In WPF you can use the Dispatcher.
In WinForms:
Try
// Get the UI thread's context in the constructor.
var context = TaskScheduler.FromCurrentSynchronizationContext();
// Then its possible to start a task directly on the UI thread
var token = Task.Factory.CancellationToken;
Task.Factory.StartNew(() =>
{
this.label1.Text = "Task past first work section...";
}, token, TaskCreationOptions.None, context);
EDIT:
The reason you are getting this error is because you are trying to access the Grid control from another thread. In general, most UI applications are in a STA(Single Threaded Affinity) model, where any interactions with the UI must be done on the "UI" thread which is usually the main/first thread the application starts on.
As you are loading the data on a background thread, after it is finished, you need a way to Marshal(invoke/run) the code which update the Grid on the Main/UI thread.
To achieve this, you create a TaskScheduler on the main thread by using its current SynchronizationContext (as in the constructor of the window/control the current context will be the UI thread) and than later you can pass that context into the Task.Factory.StartNew method as a parameter, so that it knows to "Marshal"(Invoke/Run) the code on the given "Context" which is the UI Thread
System.Threading.Tasks allows you to easily create a child task and run a completion block when all is complete. If you specify the UI context then the completion block will run in the UI thread, no need for Invoke().
Code:
var ui = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(
() =>
{
// this runs in worker thread
loadMyData();
DoSomeLengthyJob();
DoSomethingElse();
})
.ContinueWith(t =>
{
// now we are in UI thread
// now update the UI with whatever you want
// with the results from your worker thread
dataGridView1.Rows.Add();
}, ui);
Tell me more
Check out this article by Stephen Cleary
I am doing some heavy computations on the main thread and these computations cannot run on a separate thread.
I want to display a "Busy Indicator" (i.e., spinning widget) on the application UI when these computations are running. As such, I cannot show the busy indicator on main thread as the UI is locked while these computations are running.
To work around this issue, I tried to move the busy indicator to separate thread. With the help of this post I am able to place the busy indicator on separate thread. However, I am not able to communicate with this thread to start or stop the busy indicator.
private HostVisual CreateBusyIndicatorOnWorkerThread()
{
// Create the HostVisual that will "contain" the VisualTarget
// on the worker thread.
HostVisual hostVisual = new HostVisual();
Thread thread = new Thread(new ParameterizedThreadStart(BusyIndicatorWorkerThread));
thread.ApartmentState = ApartmentState.STA;
thread.IsBackground = true;
thread.Start(hostVisual);
// Wait for the worker thread to spin up and create the VisualTarget.
s_event.WaitOne();
return hostVisual;
}
private static AutoResetEvent s_event = new AutoResetEvent(false);
private void BusyIndicatorWorkerThread(object arg)
{
// Create the VisualTargetPresentationSource and then signal the
// calling thread, so that it can continue without waiting for us.
HostVisual hostVisual = (HostVisual)arg;
VisualTargetPresentationSource visualTargetPS = new VisualTargetPresentationSource(hostVisual);
s_event.Set();
// Create a MediaElement and use it as the root visual for the
// VisualTarget.
visualTargetPS.RootVisual = CreateBusyIndicator();
// Run a dispatcher for this worker thread. This is the central
// processing loop for WPF.
System.Windows.Threading.Dispatcher.Run();
}
private FrameworkElement CreateBusyIndicator()
{
var busyIndicator = new MyBusyIndicator();
//busyIndicator.DataContext = this.
Binding myBinding = new Binding("IsBusy");
myBinding.Source = this;
busyIndicator.SetBinding(MyBusyIndicator.IsBusyProperty, myBinding);
}
I always gets an exception "The calling thread cannot access this object because a different thread owns it". This is because I am trying to update the busy indicator from the main thread while the busy indicator is owned by a different thread.
I have also tried an approach given in this article,
private void CreateAndShowContent()
{
Dispatcher = Dispatcher.CurrentDispatcher;
VisualTargetPresentationSource source =
new VisualTargetPresentationSource(_hostVisual);
_sync.Set();
source.RootVisual = _createContent();
DesiredSize = source.DesiredSize;
_invalidateMeasure();
Dispatcher.Run();
source.Dispose();
}
But with this approach Dispatcher.Run() nothing happens until after the completion of the computations and then the busy indicator is displayed.
I want to communicate from main thread to the thread having busy indicator. Does anyone have an approach?
There is no reason to run "heavy computations" in UI thread. Even more - this is a bad practice. Instead use BackgroundWorker which will do work, meantime alive UI-thread will show Loading/Calculating:
var worker = new BackgroundWorker();
worker.DoWork += (s, e) => {
// This part will last at a separate thread without blocking UI.
// Excellent place for heavy computations.
}
worker.RunWorkerCompleted += (s, e) => {
// Here we're back to UI thread - so you can change states and stop animations.
}
// And finally start async computation
worker.RunWorkerAsync();
UI should contain BusyIndicator control which will be activated/stopped when you'll start/finish worker.
Please stop what you are doing... it is totally incorrect. #Anatolii Gabuza was correct... you shouldn't do any long running process using the UI thread as this will block it, making the application unusable at these times. Unless your long running process is rendering UI objects, then there really is no reason to do it using the UI thread... let us know what it is and we can help you to run it on a background thread correctly.
So you discovered that you can't display your busy indicator on the UI thread because it is busy with your long running process... at this point, most developers would realise their error, but unfortunately, not you. Instead of accepting that the long running process should be run on a background thread, you do the exact opposite and now want to display some UI element in a background thread, while blocking the UI thread with a long running process???
This is utter madness, if you want to avoid some horrendous problems, please stop. If you continue, then you'd better get used to seeing that exception:
The calling thread cannot access this object because a different thread owns it.
You need to invoke it busyContainer dispatcher. use as below
this.busyContainer.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() =>
{
//update busy Container
}));
I got this from SO but cannot find it on SO
Run this on the UI thread and put in your task where very long task is
public class WaitCursor : IDisposable
{
private Cursor _previousCursor;
public WaitCursor()
{
_previousCursor = Mouse.OverrideCursor;
Mouse.OverrideCursor = Cursors.Wait;
}
#region IDisposable Members
public void Dispose()
{
Mouse.OverrideCursor = _previousCursor;
}
#endregion
}
using (new WaitCursor())
{
// very long task
}
Before you flag my question as being a duplicate, hear me out.
Most people have a long running non-UI operation that they are doing and need to unblock the UI thread. I have a long running UI operation which must run on the UI thread which is blocking the rest of my application. Basically, I am dynamically constructing DependencyObjects at run time and adding them to a UI component on my WPF application. The number of DependencyObjects that need to be created depends upon user input, of which there is no limit. One of the test inputs I have has about 6000 DependencyObjects that need to be created and loading them takes a couple minutes.
The usual solution of using a background worker in this case does not work, because once the DependencyObjects are created by the background worker, they can no longer be added to the UI component since they were created on the background thread.
My current attempt at a solution is to run the loop in a background thread, dispatch to the UI thread for each unit of work and then calling Thread.Yield() to give the UI thread a chance to update. This almost works - the UI thread does get the chance to update itself a couple times during the operation, but the application is still essentially blocked.
How can I get my application to keep updating the UI and processing events on other forms during this long running operation?
EDIT:
As requested, an example of my current 'solution':
private void InitializeForm(List<NonDependencyObject> myCollection)
{
Action<NonDependencyObject> doWork = (nonDepObj) =>
{
var dependencyObject = CreateDependencyObject(nonDepObj);
UiComponent.Add(dependencyObject);
// Set up some binding on each dependencyObject and update progress bar
...
};
Action background = () =>
{
foreach (var nonDependencyObject in myCollection)
{
if (nonDependencyObject.NeedsToBeAdded())
{
Dispatcher.Invoke(doWork, nonDependencyObject);
Thread.Yield(); //Doesn't give UI enough time to update
}
}
};
background.BeginInvoke(background.EndInvoke, null);
}
Changing Thread.Yield() to Thread.Sleep(1) seems to work, but is that really a good solution?
Sometimes it is indeed required to do the background work on the UI thread, particularly, when the majority of work is to deal with the user input.
Example: real-time syntax highlighting, as-you-type. It might be possible to offload some sub-work-items of such background operation to a pool thread, but that wouldn't eliminate the fact the text of the editor control is changing upon every new typed character.
Help at hand: await Dispatcher.Yield(DispatcherPriority.ApplicationIdle). This will give the user input events (mouse and keyboard) the best priority on the WPF Dispatcher event loop. The background work process may look like this:
async Task DoUIThreadWorkAsync(CancellationToken token)
{
var i = 0;
while (true)
{
token.ThrowIfCancellationRequested();
await Dispatcher.Yield(DispatcherPriority.ApplicationIdle);
// do the UI-related work
this.TextBlock.Text = "iteration " + i++;
}
}
This will keep the UI responsive and will do the background work as fast as possible, but with the idle priority.
We may want to enhance it with some throttle (wait for at least 100 ms between iterations) and better cancellation logic:
async Task DoUIThreadWorkAsync(CancellationToken token)
{
Func<Task> idleYield = async () =>
await Dispatcher.Yield(DispatcherPriority.ApplicationIdle);
var cancellationTcs = new TaskCompletionSource<bool>();
using (token.Register(() =>
cancellationTcs.SetCanceled(), useSynchronizationContext: true))
{
var i = 0;
while (true)
{
await Task.Delay(100, token);
await Task.WhenAny(idleYield(), cancellationTcs.Task);
token.ThrowIfCancellationRequested();
// do the UI-related work
this.TextBlock.Text = "iteration " + i++;
}
}
}
Updated as the OP has posted a sample code.
Based upon the code you posted, I agree with #HighCore's comment about the proper ViewModel.
The way you're doing it currently, background.BeginInvoke starts a background operation on a pool thread, then synchronously calls back the UI thread on a tight foreach loop, with Dispatcher.Invoke. This only adds an extra overhead. Besides, you're not observing the end of this operation, because you're simply ignoring the IAsyncResult returned by background.BeginInvoke. Thus, InitializeForm returns, while background.BeginInvoke continues on a background thread. Essentially, this is a fire-and-forget call.
If you really want to stick to the UI thread, below is how it can be done using the approach I described.
Note that _initializeTask = background() is still an asynchronous operation, despite it's taking place on the UI thread. You won't be able to make it synchronous without a nested Dispatcher event loop inside InitializeForm (which would be a really bad idea because of the implications with the UI re-entrancy).
That said, a simplified version (no throttle or cancellation) may look like this:
Task _initializeTask;
private void InitializeForm(List<NonDependencyObject> myCollection)
{
Action<NonDependencyObject> doWork = (nonDepObj) =>
{
var dependencyObject = CreateDependencyObject(nonDepObj);
UiComponent.Add(dependencyObject);
// Set up some binding on each dependencyObject and update progress bar
...
};
Func<Task> background = async () =>
{
foreach (var nonDependencyObject in myCollection)
{
if (nonDependencyObject.NeedsToBeAdded())
{
doWork(nonDependencyObject);
await Dispatcher.Yield(DispatcherPriority.ApplicationIdle);
}
}
};
_initializeTask = background();
}
I am trying to create a thread that contains a form progress bar (just a GIF image).
I have called StartProgress() right before a large method. Basically when the thread starts it loads up the ProgressBar form (which I want to show all the time, and just hide it when it's not needed) and with ProgressActive set to true, it should display the form until ProgressActive is false, then the form should be hidden (until progress is active again). Here is what I have so far, but it freezes up on me :(
public static string ProgressInfo="Test";
public static bool ProgressActive=true;
public static bool ThreadStarted = false;
public static void StartProgress()
{
while (!ThreadStarted)
{
Thread t = new Thread(new ThreadStart(Progress));
ThreadStarted = true;
t.Start();
}
}
public static void Progress()
{
while (ThreadStarted)
{
LoadingBar lb = new LoadingBar();
lb.Show();
lb.TopMost = true;
while (ThreadStarted)
{
if (ProgressActive)
{
lb.Visible = true;
lb.lblLoadingStatus.Text = ProgressInfo;
}
else
{
lb.Visible = false;
}
Thread.Sleep(1000);
}
}
}
EDIT: I am trying to do this within a static class.
Is there any reason for not using BackgroundWorker if using .NET 2.0 or higher?
The reason I am saying that is because BackgroundWorker is event based, so it exposes an event like ProgressChanged which can reduce the overall size of your code.
The freezing is due to the fact you are trying to change your progress bar contained on the UI thread from your worker thread. I would recommend raising an event from within your worker Progress function to a handler on the UI thread. You will need to marshall the call to the handler on the thread as below.
private object _lock = new object(); //should have class scope
private void ShowProgressControl(EventArgs e)
{
if (this.InvokeRequired)
{
lock (_lock)
{
EventHandler d = new EventHandler(ShowProgressControl);
this.Invoke(d, new object[] { e });
return;
}
}
else
{
//Show your progress bar.
}
}
Enjoy!
The problem is that you need a message loop for any UI element to work correctly. Since you are creating the form in a worker thread then there is no message loop running. To create the message loop you have to call Application.Run or Form.ShowDialog both of which are blocking calls. Obviously that solution would hang up your worker thread.
The best thing to do is to create a separate thread dedicated to running the message loop and which can safely handle forms and controls. Have the worker thread periodically publish progress information to a variable that can be shared between the worker thread and the UI thread. Then have the UI thread periodically poll (using System.Windows.Form.Timer) that shared variable and update the UI accordingly.
As a side note, I would avoid using Control.Invoke or Control.BeginInvoke to push the progress information to the UI thread. You situation seems to warrant the polling approach instead. The reasons for preferring polling over pushing are:
It breaks the tight coupling between the UI and worker threads that Control.Invoke imposes.
It puts the responsibility of updating the UI thread on the UI thread where it should belong anyway.
The UI thread gets to dictate when and how often the update should take place.
There is no risk of the UI message pump being overrun as would be the case with the marshaling techniques initiated by the worker thread.
The worker thread does not have to wait for an acknowledgement that the update was performed before proceeding with its next steps (ie. you get more throughput on both the UI and worker threads).
You should create the progress bar on the main thread.
Make sure your heavy procedure runs from another thread.