Synchronising threads between C++/CLI and C# - c#

Say I have the following C++/CLI class:
public ref class ManagedDLAContainer {
private:
DLAContainer* native_dla_container;
public:
ManagedDLAContainer() : native_dla_container(new DLAContainer()) {}
~ManagedDLAContainer() { delete native_dla_container; }
KeyValuePair<int,int> GetMRAParticle() {
std::pair<int,int> mra_p = native_dla_container->mra_particle();
KeyValuePair<int,int>^ mra_kvp = gcnew
KeyValuePair<int,int>(mra_p.first, mra_p.second);
return *mra_kvp;
}
size_t Size() {
return native_dla_container->size();
}
void Generate(size_t _n) {
native_dla_container->generate(_n);
}
};
where DLAContainer is an unmanaged, native C++ class. The method generate of this class does computationally intensive calculations involving building up a system of particles, whilst mra_particle returns a std::pair<int,int> representing the most-recently-added particle to the DLAContainer. This C++/CLI code is packaged in a class library which is then used by a C# WPF project.
The WPF project has the following class:
public partial class MainWindow : Window {
private static readonly object locker = new object();
private readonly ManagedDLAContainer dla;
private KeyValuePair<int,int> mra_pair;
private readonly AggregateSystemManager aggregate_manager;
public MainWindow() {
InitializeComponent();
dla = new ManagedDLAContainer();
mra_pair = new KeyValuePair<int,int>();
aggregate_manager = new AggregateSystemManager();
// a Model3DGroup which is part of the GUI
WorldModels.Children.Add(aggregate_manager.AggregateSystemModel());
}
private void AggregateUpdateListener(uint _particle_slider_val){
while (dla_2d.Size() < _particle_slider_val) {
KeyValuePair<int,int> agg_kvp = dla.GetMRAParticle();
if (agg_kvp.Equals(mra_pair) {
// no updates to aggregate
}
else {
mra_pair = agg_kvp;
Point3D position = new Point3D(agg_kvp.Key, agg_kvp.Value,0);
aggregate_manager.AddParticle(position);
Dispatcher.Invoke(() => { aggregate_manager.Update(); } );
}
}
}
private void GenerateAggregate() {
lock(locker) {
uint particle_slider_val = 0;
Dispatcher.Invoke(() => {
particle_slider_val = (uint)particles_slider.Value;
});
// start AggregateUpdateListener in new task
Task.Factory.StartNew(() => AggregateUpdateListener(particle_slider_val));
// generate the aggregate
dla.Generate(particle_slider_val);
}
}
private void GenerateButtonHandler(object sender, RoutedEventArgs e) {
// start GenerateAggregate method in new task
Task.Factory.StartNew(() => GenerateAggregate());
}
}
Explanation of Program Flow
The user sets the number of particles to generate using the particle_slider GUI element, they then click the generate button.
The method GenerateAggregate is run in a new task using Task.Factory.StartNew, this function then runs the AggregateUpdateListener in a separate task and finally calls Generate to produce the particle system.
AggregateUpdateListener continuously runs whilst Generate is running and checks for updates to the most-recently-added particle and renders the new particles to the interface using the AggregateManager class as necessary.
The Problem
Whilst this program is mostly successful, occasionally particles generated using ManagedDLAContainer::Generate(size_t) are missed by the AggregateUpdateListener method resulting in gaps in the particle system shown in the interface.
The issue here, I believe, is that the two processes (the generation of the particle system and the checking-rendering process) are not running in a correctly synchronised way. I need to somehow get it so that when a particle is added to the system an event is fired which allows AggrgegateUpdateListener to then perform the rendering and then hand the control back to generation.
I am unsure of how to do this however, as my Generate function will run non-stop in the background until the particle system has been generated completely up to the number of particles required - and this process is executed via the native C++ code behind the scenes which has no knowledge whatsoever of my C# project. It is for this reason that I think using something like AutoResetEvent is not applicable in this case, but if it is then please do let me know how!
The only solution I can come up with at the moment (which has nothing to do with correctly synchronising the processes) is to iterate over the final particle system of the GUI and do comparison checks with the particle system container of the C++ code (which will always be correct) and fill in any missing gaps in the former when a miss is detected from comparison with the latter. But this is a nasty "solution" and I'd much rather have it correctly running in real-time.
If any further information is required, let me know.

You could try using a named Semaphore both in C++ and C# however it's probably a bit heavy as it's meant for synchronisation between processes.
Otherwise, following Hans' comment you could create a BlockingCollection in the managed C++ part and expose it to the C# project. You would then need to consume all the particles in the ManagedDLAContainer and enqueue them in the blocking queue.
In the C# GUI I'd recommend you have a timer every 200/250ms which when it fires dequeues all the available particles in the queue and then updates the GUI. Make sure to bound this by some max number of updates so that you don't get stuck constantly pulling items off the queue (if the native code is faster than the the C# code).

Related

Singleton object creation on multiple different threads using TPL

This is just a self learning situation. I am pretty new to TPL and Threading. Anyways, I am using a generic Singleton class and creating ~10K instances to check if my code is returning same instance or creating new instance everytime. I am creating instances asynchronously using Task Factory inside a for loop. To validate the creation of instance, i am returning a string having these info as a list of string:
Iteration Counter
Name of instance
Hashcode of instance and
ThreadId
and displaying the list of strings to listbox.
My Queries
On running, I found few things,
the value of i inside the for loop is getting duplicated for the different intances
for those 10K iterations, i have only 8-9 threads created, instead of expected 10k threads. I was expectig 10K threads to popup , do their individual task and then disappear gracefully.
Can I use this in my projects, as class libraries, irrespective of the platforms - Web, Windows or Mobile?
Please do leave a note on my 1OK threads thoughts :). Whether its a good idea / bad idea on multithreading?
My code
Singleton Class
public sealed class Singleton<T> where T : class
{
static Singleton() { }
private Singleton() { }
public static T Instance { get; } = Activator.CreateInstance<T>();
}
Class: SingletonInThread
public class SingletonInThread
{
/// <summary>
/// Method responsible for creation of same instance, 10K times using Task.Factory.StartNew()
/// </summary>
/// <returns></returns>
public async Task<IEnumerable<string>> LoopAsync()
{
List<Task<string>> list = new List<Task<string>>();
for (int i = 0; i <= 9999; i++)
{
list.Add(Task.Factory.StartNew(()=> CreateAndLogInstances(i)));
}
return await Task.WhenAll<string>(list);
}
/// <summary>
/// Creates new instance of Logger and logs its creation with few details. Kind of Unit of Work.
/// </summary>
/// <param name="i"></param>
/// <returns></returns>
private string CreateAndLogInstances(int i)
{
var instance = Singleton<Logger>.Instance;
return $"Instance{i}. Name of instance= {instance.ToString()} && Hashcode ={instance.GetHashCode()} && ThreadId= {Thread.CurrentThread.ManagedThreadId}";
}
}
Frontend
_
On UI side, On buttonclick event, populating listbox
private async void button1_Click(object sender, EventArgs e)
{
IEnumerable<string> list = await new SingletonInThread().LoopAsync();
foreach (var item in list)
{
listBox1.Items.Add(item);
}
}
Also, I noticed one thing that my UI gets blocked while populating list box with 10K items. Please do help me populating it asynchronous way. I knew the bgworker, begininvoke and methodinvoker. Is there anything other than the too in TPL??
Output
---
Update
As suggested if I use Parallel.For,then, instead of 10K strings, I am getting a random figure of 9491, 9326 etc. I.e. less than 10K. I dont know why????
Here's my updated code for LoopAsync method using Parallel.For
public IEnumerable<string> LoopAsync()
{
List<string> list = new List<string>();
Parallel.For(0, 9999, i =>
{
list.Add( CreateAndLogInstances(i));
});
return list;
}
the value of i inside the for loop is getting duplicated for the different intances
This doesn't have anything to do with threading/parallel/asynchrony or singleton instances. You're seeing this because closures capture variables, not values. So this code:
for (int i = 0; i <= 9999; i++)
{
list.Add(Task.Factory.StartNew(()=> CreateAndLogInstances(i)));
}
is passing the variable i to the closure () => CreateAndLogInstances(i), not the current value of i. To capture the current value and use that in your closure, you would need a separate variable per closure, as recommended in a comment:
for (int i = 0; i <= 9999; i++)
{
var index = i;
list.Add(Task.Factory.StartNew(()=> CreateAndLogInstances(index)));
}
for those 10K iterations, i have only 8-9 threads created, instead of expected 10k threads. I was expectig 10K threads to popup , do their individual task and then disappear gracefully.
No, you would very much not want that to happen. Thread creation and destruction has a lot of overhead. StartNew and Parallel queue work to the thread pool, and the thread pool will grow quickly to a certain point and then grow slowly, on purpose. This is because on, e.g., an 8-core machine, there is no point in having 10k threads because they cannot all run anyway.
Can I use this in my projects, as class libraries, irrespective of the platforms - Web, Windows or Mobile?
I never recommend using parallel processing on web applications, because your web host has already parallelized your requests. So doing additional parallel processing tends to burden your web server and potentially make it much less responsive to other requests.
Also, I noticed one thing that my UI gets blocked while populating list box with 10K items. Please do help me populating it asynchronous way.
You normally want to avoid making 10k UI updates at practically the same time. Parallel processing doesn't help with a UI because all UI updates have to be done on the UI thread. Either put all the results in the list with a single call, or use something like control virtualization.
Adding the same object to a WinForms list box multiple times results in multiple lines in the list box, e.g.:
private void Form1_Load(object sender, EventArgs e)
{
string foo = "Hello, world";
listBox1.Items.Add(foo);
listBox1.Items.Add(foo);
listBox1.Items.Add(foo);
}
yields three lines proclaiming Hello, world. So, it isn't unexpected that you receive 10,000 lines in your example. But are they the same object, or are you creating multiple objects?
I created my own Logger class:
public class Logger
{
static private Random rnd = new Random();
public int Id { get; } = rnd.Next();
public override string ToString()
{
return Id.ToString();
}
}
Indeed, each output line has the same Id, thus indicating the same object instance was used in each case. You also output the call to GetHashCode(), which also is the same in each case, indicating a high probability that you are dealing with only one instance.

Is there a way to await a flag change in a function?

I've attempted to make a simple step mode for an algorithm I'm running, and here is how it looks like:
public async Task<bool> AStarAlgorithmAsync(PFSquare curr = null)
{
// some algorithm code here
foreach(var square in Sorroundings)
{
if (SteppedMode)
{
await Task.Run(Pause);
}
if (await AStarAlgorithmAsync(square))
{
return true;
}
}
}
In my application, I have a Boolean called SteppedMode that decides if the algorithm should run one iteration per click event.
Pause() looks like this:
private void Pause()
{
while (!ContinueStep) { }
ContinueStep = false;
return;
}
And in another part of my (GUI) application I have an event which sets the boolean ContinueStep to true which in theory should end the while loop and continue the algorithm function. Currently this bit of code locks my GUI thread up and I'm almost certain there is a better way to do this.
I'm trying to get my algorithm function to run one iteration, wait for a click from the user and only then continue running the algorithm. Is there an easier and cleaner way to do this?
(This is a GUI application, not a console application.)
Your property is moonlighting as a method.
It makes no sense to set a property, to then have that property revert back to its original state immediately. As a consumer, I would be majorly confused by that behavior. Think about this code:
var myObj = new MyObject();
myObj.MyBoolean = true;
Console.WriteLine(myObj.MyBoolean); // FALSE!?
It just doesn't make sense.
The only effect you want to trigger by setting this property is to execute some code. That's exactly what methods are supposed to be used for:
public void ContinueStep()
{
Console.WriteLine("I did some work");
}
So instead of this:
myObj.ContinueStep = true;
you should be doing this:
myObject.ContinueStep();
This doesn't lock up your UI thread, while also being a lot more sensical to your consumer. The method suggests that some action will be taken (which may or may not lead to state changes in the object - that's a contextual expectation).
Infinite recursion
As an aside; based on your code, AStarAlgorithmAsync is a recursive function, and seemingly infinitely so. There doesn't seem to be an ending condition.
Every recursive level will interate over the first surrounding and then trigger the next level, which again will interate over the first surrounding and then trigger the next level, which again ...
That can't be right, but it's unclear to me how to fix it as the bigger picture is not explained in your question
A simple implementation
What I'm trying to do is get my algorithm function to run one iteration, wait for a click from the user and only then continue running the algorithm, is there an easier and cleaner way to do this?
A simple example of such a thing:
private int _index = 0;
private List<object> _myList = ...; // assume this list contains some elements
public void ProcessNextObject()
{
if(_index < _myList.Length)
{
Process(_myList[_index]);
_index++;
}
}
private void Process(object o)
{
Console.WriteLine("Processing this object!");
}
You can then hook up your click event to call ProcessNextObject().
Note that in this example, the list is processed once and cannot be processed again. By manipulating the index value, you can change that behavior as you like.

Generic BeginInvoke Scheme to ensure function calls in same threading context

I'm moving some code from a winforms control object to a separate object for better modularity. However, there some calls to an external object issuing callbacks, which I have no control of and which can be fired from different threads as the main UI thread. To avoid this I use the well known BeginInvoke scheme to check, whether a call should be transfered to the main UI thread.
When I now move this code to my separated object, I have not necessary a Winforms reference anymore. I could handle over a Control object to still ensure that everything is running in the same thread. But I would rather like to have a generic mechanism which does exactly the same like ensuring, that the Threadconext in which the e.g. the object was created or a specific entry function was called is also used for subsequent calls issued e.g. by external callbacks.
How could this achieved most easily ?
Example:
public class Example
{
ThreadedComponent _Cmp = new ThreadedComponent();
public Example()
{
_Cmp.ThreadedCallback += new ThreadedComponent.CB(Callback);
}
public void StartFunction()
{
// called in ThreadContextA
_Cmp.Start();
}
void Callback(Status s)
{
// is called in ThreadContextB
if(s == SomeStatus)
_Cmp.ContinueFunction(); // must be called in ThreadContextA
}
}
For clarification
ContinueFunction must be called from the same ThreadContext like StartFunction was called. This is not necessarily a UI thread, but at the moment it is of course a button handler.
There is no 'generic' scheme, your class cannot make a lot of assumptions about what thread it is used on and what object can provide the BeginInvoke() method you need. Choose from one of the following options:
Do not help at all, simply document that the event can be raised on a worker thread. Whatever code exists in the GUI layer can of course always figure out how to use BeginInvoke() when needed.
Allow the client code to pass a Control object through your class constructor. You can store it and call its BeginInvoke() method. That works, it isn't terribly pretty because your class now is only usable in a Winforms project.
Expose a property called "SynchronizingObject" of type ISynchronizeInvoke. The GUI layer now has the option to ask you to call ISynchronizeInvoke.BeginInvoke(). Which you do if the property was set, just fire the event directly otherwise. Several .NET Framework classes do this, like Process, FileSystemWatcher, EventLog, etc. It however has the same problem as the previous solution, the interface isn't readily available in a non-Winforms application.
Demand that the client code creates your object on the UI thread. And copy SynchronizationContext.Current in your constructor. You can, later, use its Post() method to invoke. This is the most compatible option, all GUI class libraries in .NET provide a value for this property.
Do keep the trouble in mind when you choose one of the latter bullets. The client code will get the event completely unsynchronized from your thread's code execution. A concrete event handler is somewhat likely to want to access properties on your class to find out more about the state of your class. That state is unlikely to still be valid since your thread has progressed well past the BeginInvoke() call. The client code has no option at all to insert a lock to prevent that from causing trouble. You should strongly consider to not help at all if that's a real issue, it often is.
In C# you cannot assign a thread context to an object, like in Qt for example (C++).
A thread is running in itself, it does not "collect" objects or methods to call them if they were marked somehow.
However synchronizing to a GUI thread in C# is very easy. Instead of the BeginInvoke/Invoke pattern, you can create a System.Windows.Forms.Timer instance, which can call the methods on the non-WinForms objects.
Example:
public interface IMyExternalTask
{
void DoSomething();
}
// ...
List<IMyExternalTask> myTasks = new List<IMyExternalTask>();
System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();
t.Interval = 1000; // Call it every second
t.Tick += delegate(object sender, EventArgs e) {
foreach (var myTask in myTasks)
myTask.DoSomething();
};
t.Start();
In the example your "external" objects must implement the interface, and they can do their tasks from the DoSomething() method, which will be synchronized to the GUI thread.
These external objects don't have to have any reference to any Windows.Forms object.
I solve the problem using a separate queue which runs its own thread. Function Calls are added to the Queue with a Proxyinterface. It's probably not the most elegant way, but it ensures, that everything added to the queue is executed in the queue's threadcontext. This is a very primitive implementation example just to show the basic idea:
public class Example
{
ThreadQueue _QA = new ThreadQueue();
ThreadedComponent _Cmp = new ThreadedComponent();
public Example()
{
_Cmp.ThreadedCallback += new ThreadedComponent.CB(Callback);
_QA.Start();
}
public void StartFunction()
{
_QA.Enqueue(AT.Start, _Cmp);
}
void Callback(Status s)
{
// is called in ThreadContextB
if(s == SomeStatus)
_QA.Enqueue(new ThreadCompAction(AT.Continue, _Cmp);
}
}
public class ThreadQueue
{
public Queue<IThreadAction> _qActions = new Queue<IThreadAction>();
public Enqueue(IThreadAction a)
{
lock(_qActions)
_qActions.Enqueue(a);
}
public void Start()
{
_thWatchLoop = new Thread(new ThreadStart(ThreadWatchLoop));
_thWatchLoop.Start();
}
void ThreadWatchLoop()
{
// ThreadContext C
while(!bExitLoop)
{
lock (_qActions)
{
while(_qActions.Count > 0)
{
IThreadAction a = _qActions.Dequeue();
a.Execute();
}
}
}
}
}
public class ThreadCmpAction : IThreadAction
{
ThreadedComponent _Inst;
ActionType _AT;
ThreadCmpAction(ActionType AT, ThreadedComponent _Inst)
{
_Inst = Inst;
_AT = AT;
}
void Do()
{
switch(AT)
{
case AT.Start:
_Inst.Start();
case AT.Continue:
_Inst.ContinueFunction;
}
}
}

How to access & use an object which has been created on a different thread in WPF

I am having following scenario that I need to show preview option in my application like what ms-word does. When we click the info option under File menu item, then preview of document is shown.
In the same way, I also want to show the preview of my data rendering part in my application when someone clicks File\Info panel. For this i have written a method which gets the preview or screenshots of my app but that method is taking some time So when somebody click on the File menu then application hangs for a while. So, i tried to call that method on different thread using background worker as well as normal thread mechanism. but the thing is that method I am calling on different thread it returns an image source object and when I try to access that object on run worker completed event of background worker, then it shows an exception like owner of this object is a different thread which means that returned image has been created on a different thread therefore I can't use it. So, what is the optimized way to get and use that image in my case.
Code tends to be like this.
public void ShowPreview()
{
ImageSource source =null;
var bgWorkerThread = new BackgroundWorker()
bgWorkerThread.DoWork +=(SENDER,ARGS)=> {
source = planView.GetPreviewImage();
}
bgWorkerThread.RunWorkerCompleted += (sender,args)=>
{
// Application crashes at this point
infoPanel.PreviewImage.source = args.Result as ImageSource;
}
}
you can use invoke or you could create a "storage class" (i think its called a singleton but I'm not sure) reuse the same instance across several classes and/or threads like this.
class Test
{
void main()
{
newThread nt = new newThread();
Storage store = new Storage();
nt.store = store;
Thread t = new Thread(new ThreadStart(nt.runMe));
t.Start();
}
}
public class newThread
{
public Storage store;
public void runMe()
{
store.someNum = 8;
}
}
public class Storage
{
public int someNum;
}

Static variable value different in background agent

I have an app that shows some data and starts a background agent to update live tiles dinamically. Because of live tiles content is created in background agent using some var populated from main thread, I decided (maybe this was a wrong decision, but it's the only one I thought reasonable) to write a class with static variables and properties to share between main thread and background agent.
Now the problem is I write a variable value in main thread, but when background agent executes finds this value null. Why?
I provide a small example, hopping it's enough for you to understand.
STATIC PART
public class Vars
{
public static IEnumerable<Contact> Contacts;
public static void Test()
{
int num = Contacts == null ? -2 : Contacts.Count();
// num is -2 here because Contacts is null !!
}
}
BACKGROUND AGENT
public class TileAgent : ScheduledTaskAgent
{
protected override void OnInvoke(ScheduledTask task)
{
// It's necessary to use BeginInvoke to avoid Cross-thread errors
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
Vars.Test();
});
NotifyComplete();
}
}
MAIN PAGE
public partial class MainPage : PhoneApplicationPage
{
private void Contacts_SearchCompleted(object sender, ContactsSearchEventArgs e)
{
busyIndicator.IsRunning = false;
try
{
Vars.Contacts = e.Results
.Where(.........);
ContactResultsData.DataContext = Vars.Contacts;
// Vars.Contacts.Count() = 67 here !!!
if (Vars.GetTile() != null)
StartAgent();
}
catch (System.Exception)
{
// That's okay, no results
}
}
private void ContactResultsData_Tap(object sender, GestureEventArgs e)
{
int num = Vars.Contacts == null ? -2 : Contacts.Count();
// num = 67 here !!
}
}
What's wrong with my code? Is there a better way to accomplish my task?
Consider I'm working on Windows Phone from less than one month, so I'm sure I'm still doing very bad things...
UPDATE:
After putting correct locks to avoid concurrent read/write from different threads, I decided to put an explicit static constructor to static class
public class Vars
{
static Vars()
{
Debug.WriteLine("init");
}
}
and this is called everytime background agent is invoked!!
This explains the reason I see my variable as null, but I don't understand: why a static class is recreated every time?
Could it be because background agent is inside a dll project (it's necessary to run it)?
Is there a way to make a single class, created only first time, that can be shared among different threads (are they processes in this situation?)?
After a long search, I finally found an article stating:
Since our EvenTiles application and its PeriodicTask are running in
separate processes, they are completely separated from each other,
meaning that they get their own copies of variables they both want to
access, even though these variables are defined in a separate project.
So it's impossible to share data between main app and periodic task using "simple" static variables/properties; we must read/write a database or the isolated storage or whatever we please.
I find this crazy, but this is the story.
You need to synchronize access to the shared collection. Right now one thread can read it (by calling Count() while the other writes, and this is very bad.
i think that add volatile modifier to your variable can resolve your problem.

Categories