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.
Related
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).
The application takes a lot of database queries. Request is created after the event made by the user or through the use of several timer (10 sec tick).
The problem occurs when the database server suddenly becomes unavailable. This causes a huge amount of on-screen messages containing information about the error in the connection.
I would like to achieve a situation in which a failed open call will freeze the application and open a single window that indicates a problem where the connection attempt will be retried every X seconds (plus a progress bar). If the connection is restored window is closed and the application will unlock.
How to do it? Please assumptions / guidelines or examples of ready-made solutions.
So if I understand you right, it's a usability problem. Your goal is for your users to be happy & confident that all is well, whilst waiting for a db connection. You don't want: panicky users pressing random buttons, phoning for help and complaining. You don't want a load of meaningless technical error messages; nor a frozen app with no messages. But you will accept a temporarily frozen app with a good helpful message.
Good usability doesn't come cheap. If you want to allow the user to cancel, then you have to learn some multi-threading. For that, I'd start here: http://msdn.microsoft.com/en-us/library/ms951089.aspx. You can avoid this if you are satisfied with a static message saying 'please wait, database connection may take up to xxx seconds...'.
I take a wild guess that your WinForms app calls the database from lots of places, but you'd like something that doesn't take days of re-writing.
The simplest single-threaded solution I can think of is to define a PleaseWaitForm and a 'wrapper' method, which I'll call DoWithPleaseWait(), which will go round all your business logic/data access calls, showing and hiding the please wait form:
namespace WinFormsPleaseWaitExample
{
//You don't need these 2 lines if you have .Net 3 or later
public delegate void Action();
public delegate TResult Func<TResult>();
//
public partial class Form1 : Form
{
private readonly Form pleaseWaitForm;
public Form1()
{
InitializeComponent();
pleaseWaitForm = new PleaseWaitForm {Owner = this};
}
private void button1_Click(object sender, EventArgs e)
{
var result= DoWithPleaseWait(delegate { return SomeBusinessLayerClass.ADataRetrieval("boo"); });
MessageBox.Show(result.ToString());
}
private void button2_Click(object sender, EventArgs e)
{
DoWithPleaseWait(delegate { SomeBusinessLayerClass.ADataOperation("boo"); });
}
public void DoWithPleaseWait(Action action)
{
pleaseWaitForm.Show();
action.DynamicInvoke();
pleaseWaitForm.Hide();
}
public TResult DoWithPleaseWait<TResult>(Func<TResult> func)
{
pleaseWaitForm.Show();
TResult result = (TResult)func.DynamicInvoke();
pleaseWaitForm.Hide();
return result;
}
}
public class SomeBusinessLayerClass
{
public static void ADataOperation(string someInput)
{
//Do something that might take several seconds...
Thread.Sleep(3000);
}
public static object ADataRetrieval(string someInput)
{
//Do something that might take several seconds...
Thread.Sleep(3000);
return someInput + " returned";
}
}
}
I made a program that loads a bunch of computer information. In the Form_Load event I have it initialize 3 (that number will grow) panels of information. One that has a bunch of unit information seems to make the program load rather slowly. I've tried to speed it up a bunch by switching from WMI to using Native calls, which helped a bunch. Soon though I'm going to have network information posted as well. I used to load that panel but i disabled it for a little bit till I work out the bugs in my other panels. So while learning how I can use a seperate thread to update my battery information I figured that I might be able to create seperate threads in my unit information panel so that it might could load faster. I dont know that any of my information would cause concurrent issues, but i can work on that.
I want to start small so what if i change this
private void Form1_Load(object sender, EventArgs e)
{
unitInformationPanel1.PopulateUnitInformation();
batteryInformationPanel1.InitializeBatteries();
magStripeReaderPanel1.SetupPointOfSale();
}
to this
private void Form1_Load(object sender, EventArgs e)
{
Thread infoThread = new Thread(new ThreadStart(unitInformationPanel1.PopulateUnitInformation));
infoThread.Start();
batteryInformationPanel1.InitializeBatteries();
magStripeReaderPanel1.SetupPointOfSale();
}
would the info thread be terminated when populate unit info is done? or would it be better to move that thread creation into PopulateUnitInformation? here is what it looks like.
public void PopulateUnitInformation()
{
unitModelLabel.Text = Properties.Settings.Default.UnitModelString;
serialNumberLabel.Text = Properties.Settings.Default.UnitSerialString;
biosVersionLabel.Text = UnitBios.GetBiosNumber();
osLabel.Text = OS.getOSString();
cpuLabel.Text = UnitCpu.GetCpuInfo();
var hdd = HddInfo.GetHddInfo();
diskNameLabel.Text = hdd.Name;
diskCapacityLabel.Text = hdd.Capacity;
diskFirmwareLabel.Text = hdd.Firmware;
memoryLabel.Text = MemoryInformation.GetTotalMemory();
NetworkPresenceInformation.GetAdapatersPresent();
biometricLabel.Text = BiometricInformation.IsPresent ? "Present" : "Not Present";
var networkAdaptersPresense = NetworkPresenceInformation.GetAdapatersPresent();
bluetoothLabel.Text = networkAdaptersPresense[0] ? "Present" : "Not Present";
wifiLabel.Text = networkAdaptersPresense[1] ? "Present" : "Not Present";
cellularLabel.Text = networkAdaptersPresense[2] ? "Present" : "Not Present";
}
--
wow i just ran it with the infothread and it still took some time to load (might be the 12 panels i created in the main thread. but it loaded the 12 frames and the unit information panel populated its information after everything loaded. That was cool, but is it safe? is it somewhat easy to make 12 threads for my panels? or is that dumb?
EDIT
this is what i did for stopwatch.
Stopwatch programTimer;
public Form1()
{
programTimer = Stopwatch.StartNew();
InitializeComponent();
SetupDebugWindow();
TerminateKeymon();
UnitModel.SetModel();
UnitSerialNumber.SetSerialNumber();
}
private void Form1_Shown(object sender, EventArgs e)
{
audioBrightnessPanel1.UpdateBrightnessTrackbar();
applicationLauncherPanel1.LoadApplications();
programTimer.Stop();
Console.WriteLine("Load Time: {0}",programTimer.ElapsedMilliseconds);
timer1.Start();
}
Will this be accurate?
EDIT 2 6/18/2012
Well I took the advice of using backgroundworker. Please let me know if i did this right.
private void Form1_Load(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
void BackgroundWorker1DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
unitInformationPanel1.PopulateUnitInformation();
batteryInformationPanel1.InitializeBatteries();
magStripeReaderPanel1.SetupPointOfSale();
}
You've asked a very broad question, but I'm going to give some general advice. If you want more specific information, you should consider deleting this question and posting more specific individual questions.
First and foremost, you should very strongly consider using something like the System.Threading.Task class for your multithreaded operations. There is a ton of information online about how to get started with it and how you can use Tasks to manage asynchronous operations. The short story is that if you're spinning up your own thread (as you're doing above), you almost certainly should be using something else to do that for you.
Adding multithreading to your code will not, in the strictest sense of the word, make it any "faster"; they will always take the same amount of total processor time. What it can and will do is two things: free up the UI thread to be responsive and allow you to split that "total processor time" across multiple cores or processors, should those be available to the system. So, if you have operation X that takes 10 seconds to complete, then just shifting operation X to another thread will not make it complete any faster than 10 seconds.
No, what you are doing above is not safe. I'm assuming that somewhere you've turned off checking for cross-thread communication errors in your app? Otherwise, that code should throw an exception, assuming this is a WinForms or WPF application. This is one reason to use Tasks, as you can easily separate the part of your process that actually takes a long time (or isn't UI related), then add a task continuation that uses the results and populates the UI elements within a properly synchronized context.
So my final approach this was as follows. I felt that my Main Form was doing more than it should. Sticking with the single responsibility principle I decided that MainForm should only be responsible for one thing, showing and displaying all 12 panels (now down to 11, i turned one into a menu item). So moved all the multithreading out of mainform and into program.cs. I found that this was even a little more difficult. What I did find though was a simple solution that allows me to not even worry about multithreading at all. It was the Idle event. Here is what i chose to do.
[STAThread]
static void Main()
{
DateTime current = DateTime.Now;
DateTime today = new DateTime(2012,7,19);
TimeSpan span = current.Subtract(today);
if (span.Days<0)
{
MessageBox.Show("Please adjust Time then restart Aspects","Adjust Time");
Process.Start("timedate.cpl").WaitForExit();
}
else
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Idle += new EventHandler(Application_Idle);
mainForm = new MainForm();
mainForm.Closing += new CancelEventHandler(mainForm_Closing);
#if !DEBUG
TerminateKeymon();
StartSerial();
SetupDefaultValues();
EmbeddedMessageBox(0);
#endif
Application.Run(mainForm);
}
}
static void Application_Idle(object sender, EventArgs e)
{
Application.Idle -= Application_Idle;
mainForm.toolStripProgressBar1.Increment(1);
UnitInformation.SetupUnitInformation();
mainForm.toolStripProgressBar1.Increment(1);
Aspects.Unit.HddInfo.GetHddInfo();
mainForm.toolStripProgressBar1.Increment(1);
for (int i = 0; i < mainForm.Controls.Count; i++)
{
if (mainForm.Controls[i] is AbstractSuperPanel)
{
try
{
var startMe = mainForm.Controls[i] as AbstractSuperPanel;
startMe.StartWorking();
mainForm.toolStripProgressBar1.Increment(1);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + mainForm.Controls[i].ToString());
}
}
}
mainForm.toolStripProgressBar1.Value = 0;
}
to sum up what that does is is I add a idle listener event. Once the thead goes idle (basically meaning that Mainform is finished drawing and making all 12 panels and is showing on my desktop) I then kill the idle event listener and tell all my panels and classes to start working one at a time, updating my progress bar as I go. It works great. The load time is still the same as it was before, but there is window visibile after only a few seconds. Maybe not the best use of resources, but i think the solution is simple and straight forward.
I had a question somewhat related to this for Mobile app development a few months back (see How to write a Trigger?), and Marc "the man" Gravell posted back with a simple class that I modified to return data to my main application whenever the thread was complete.
The actual class I put into use has loads of pointless data (for you), so I'm going to paste in a revised version of Mr. Gravell's code using techniques which I used to make them work:
First, I had to create my own EventArgs class:
public class SuperEventArgs : EventArgs {
private object data;
public SuperEventArgs(object data) : base() {
this.data = data;
}
public object Data { get { return data; } }
}
Using that, here is a class I created to pass my data back to the main thread:
public delegate event DataChangedHandler(object sender, SuperEventArgs e);
public class Simple1 {
private object parameter1, parameter2;
private Control parent;
#if PocketPC
public delegate void MethodInvoker(); // include this if it is not defined
#endif
public Simple1(Control frmControl, object param1, object param2) {
parent = frmControl;
parameter1 = param1;
parameter2 = param2;
}
public event DataChangedHandler DataChanged;
public void Start() {
object myData = new object(); // whatever this is. DataTable?
try {
// long routine code goes here
} finally {
if (DataChanged != null) {
SuperEventArgs e = new SuperEventArgs(myData);
MethodInvoker methInvoker = delegate {
DataChanged(this, e);
};
try {
parent.BeginInvoke(methInvoker);
} catch (Exception err) {
Log(err); // something you'd write
}
}
}
}
}
Back in the actual main thread of execution, you'd do something like this:
public partial class Form1 : Form {
private Simple1 simple;
public Form1() {
object query = new object(); // something you want to pass in
simple = new Simple1(this, query, DateTime.Now);
simple.DataChanged += new DataChangedHandler(simple1_DataChanged);
Thread thread = new Thread(simpleStart);
thread.Start();
}
private void simpleStart() {
if (simple != null) {
simple.Start();
}
}
private void simple1_DataChanged(object sender, SuperEventArgs e) {
MyFancyData fancy = e.Data as MyFancyData;
if (fancy != null) {
// populate your form with the data you received.
}
}
}
I know it looks long, but it works really well!
This is not anything I have actually tested, of course, because there isn't any data. If you get to working with it and you experience any issues, let me know and I'll happily help you work through them.
~JoeP
I'm trying to optimize my code to be called from both an UI-less commandline call or call it from the UI.
The problem is that I have is I have written the lets call It worker-code inside the Form-class.
Now I want to pull out that worker code into a separate class.
Lets make a small sample to make my needs clearer:
public partial class form1 :Form
{
void AddLogmessage(String msg)
{
// update an listview
ListViewItem item = new ListViewItem();
item.Text = msg;
// Add the item to the ListView
LogView.Items.Add(item);
}
// button on ui to start working
private void btnStartTestRun_Click(object sender, EventArgs e)
{
try
{
DoSomeWork();
}
catch(Exception ex)
{}
}
private void DoSomeWork()
{
// do some really generic hard work....
AddLogMessage("working");
// do some more generic long lasting hard work....
AddLogMessage("working goes on...");
// in case of an error throw Exception
}
Now I want to refcator the worker code to work outside the form class, but be able to report the things that happen to the UI (if there is one) or to call the workercode without UI and do other reportings to an different target (communicate with other library which reports the results to an server)
Something like this:
public void AutomaticTaskHandler()
{
string[] cmdline = Environment.GetCommandLineArgs();
Arguments args = new Arguments(cmdline);
if (args["automatic"] != null)
{
doSomeWork();
}
}
In this case I don't have to report the Messages to the UI, but send some other messages (NOT the same Messages!!) to an server.
So my question is how do I make this the best way not having to write the doSomeWork - code twice but be able to send only the messages which are in the current scene are needed?
I thought about Delegates and Events, but I'm not too familiar to this to make this work.
Any help will be appreciated.
Thanks Meister_Schnitzel
Basically, you would create an interface IMessageTarget with a method SendMessage. Your UI code would create an implementation of that interface that outputs the messages to the UI and your console code would create an implementation of that interface that sends the messages to a server. On calling the doWork method, you would supply an instance of IMessageTarget.
Hello yeah I'm asking this question a second time, sorry about that but I don't know how to bump previous question. I'll explain more in depth my problem in a more completed example.
Instead of writing like 300+ Event classes in 300 class files which I may have to do if this doesn't work, so they can do little timed jobs like this example job below in a server project.
What i'm trying to avoid is writing a bunch of classes and simply just write everything more compacted in structure of whatever i'm working on.
To sum it up, i'm mixing 90% functional programming and want to give some function some delayed timed event, without creating the new timed event in a separate class then running back and forth through the files looking how everything is linked up, but this way everything can be seen so you can find bugs and whatnot much faster as everything is right in front of you, kinda like writing loop code, but with delay.
All I have right now is one thread which processes events, deletes events which have been stopped, keeps re-running events which don't stop after one cycle and of course waiting until some events can be ran.
If anyone knows a better way to do what i'm trying to do maybe some built-in C# Event system? Which is preferably simple.
class Event {
private Action action;
private bool stopped;
public Event(long tick, Action action) {
this.tick = tick;
this.action = action;
this.lastRun = Environment.TickCount;
}
public void stop() {
stopped = true;
}
public bool canRun() { //blah ignore just showing what I plan to do
if (stopped)
return false;
return (Environment.TickCount - lastRun) > tick;
}
public void run() {
this.lastRun = Environment.TickCount;
action();
}
//... other methods
}
class Test {
string t;
public void setT(string t) {
this.t = t;
}
public void stuff() {
Console.WriteLine(a);
}
}
class ImportantWork {
public static void Main(string[] args) {
someDeepMethod();
}
void someDeepMethod() {
Test t = new Test();
t.setT("secondTime");
//Here is where the problem occurs.
Server.registerEvent(new Event(5000, () => {
this.stop(); //<-- Error how I call this from this new Event instance.
stop(); //<-- Also error
//Event.stop(); //<-- haha may work if it was static but thats stupid
t.stuff();
Console.WriteLine("thirdTime");
}));
t.setT("firstTime");
t.stuff();
}
}
Expected output:
firstTime
...waits 5 seconds...
secondTime
thirdTime
I don't know how you'd be able to do that inline like that. Why can't you use some kind of set-function and make it two lines?
MyEvent newEvent;
Server.registerEvent((newEvent = new MyEvent(5000)));
newEvent.setAction(() => {
newEvent.stop();
t.stuff();
Console.WriteLine("thirdTime");
});
It seems to me like there's some kind of structural issue with your design. I'm assuming that the example you provided was not actually what you were working with, just a simple example to address the problem you're having. If it is, however, the example you're working with why don't you just add a boolean flag in the constructor to tell the instance whether or not to call this.stop() on itself - instead of requiring it specified in the Action?
Best of luck!