I am working on the following program which deals with threads and thread priorities.
I have constructed a windows form containing a rich textbox (DisplayTextBox) and two buttons (StartButton for running app and ExitButton for closing app).
In the form, I am creating several threads and running them one after another. The method used by each thread is found in the Threading class. The method in question is PrintOnScreen().
In this method, I am appending the thread name as well as its priority to str of type StringBuilder. Then I want to display the contents of str in DisplayTextBox (which is in Form.cs).
However, I am getting a "NullReferenceException was unhandled: Object reference not set to an instance of an object" error. The line where the error crops up is the following:
DisplayTextBox.Text = Convert.ToString(str);
Can you please help me to solve this error? Thanks.
Edit
Thanks to all for your help. In order to solve the problem, I copied the PrintOnScreen method to the Form.cs class and discarded Threading.cs.
I later used the code given by Anand and placed it below t2.Join(). Now it works like a charm.
The problem occurs in the constructor of your form. You declare DisplayText again as local member, so that the field of your form isn't initialized. Change your constructor like this:
private void Form1_Load(object sender, EventArgs e)
{
DescTextBox.Visible = false;
DisplayTextBox = new RichTextBox();
DisplayTextBox.Location = new Point(15, 31);
DisplayTextBox.Height = 258;
DisplayTextBox.Width = 303;
panel1.Controls.Add(DisplayTextBox);
}
and it should work like you expect.
Edit: But beware of the problems you will get, when you want to change UI elements from a background worker thread. In those cases you will have to use the invoke pattern.
I tried this in simple console application and it worked fine.
The issue is with DisplayTextBox. If you want to interact with any control, then you have to use UI thread or Dispatcher.
Use the following code in your Threading Class,
instead of
DisplayTextBox.Text = Convert.ToString(str);
use this one
Dispatcher.Invoke(DispatcherPriority.Normal,
new Action(
delegate()
{
DisplayTextBox.Text = Convert.ToString(str);
}
));
You cannot communicate with controls from any other thread than main application's thread. You need to use the dispather for this. Have a look here: http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.aspx
EDIT
#Fischermaen - heh, didn't notice this but it still won't work because of the line, where he wrote it fails. He still needs to use dispatcher to set the Text property on the control from the non-main threads
EDIT 2
Related threads:
How to update the GUI from another thread in C#?
In WinForms, why can't you update UI controls from other threads?
Um.
Can't see from here, but part of the reason you are having difficulty is the lack of encapsulation and poor lifetime management in your code.
Instantiate str inside the PrintOnScreen method, give it a better name as well, no appranrent need to be a member variable, no need at all to make it public.
Instead of having a void result, have it return the string result
e.g.
SomeTextBox = PrintOnScreen(); // (GetThreadDetails might be a better name...)
As a tip don't mix presentation and logic. Keep you UI controls thoroughly inside whatever owns them.
And don't do
public SomeType SomeName;
make it a property and give it getter and a setter , even if it's the short form
public SomeType SomeName {get; set;}
Any other bit of code could do something really foolish like
Form1.SomeType = (SomeOtherType)someVar; // with appaling consequences.
Nothing should have more than one owner, any other path leads to ruin.
PS str.ToString() would be a better option than Convert.ToString(str);
Well, this is not very clear for me what you are trying to achieve, however the problem is that the base form Threading class inherits from not being loaded when you are trying to access control on it (window handle still not exists) Also this is the reason you see nothing on Form1 itself, because your threads outputs into hidden form, which is not shown.
I think that you are trying to solve thread access issue, raised by SOReader. This is not proper way to do this.
Related
Previously I was working on an implementation of DynamicObject data binding (see Dynamic object two way data binding), and the solution works great. Since then I have run into the need to be able to update the values from different threads it seems to break the bindings. I am able to update the DynamicObject instance from multiple threads however am unable to keep the bindings updated.
I tried to implement the SynchronizedNotifyPropertyChanged solution provided by Cody Barnes in the SO: INotifyPropertyChanged causes cross-thread error with no success.
Any help with binding a DynamicObject implementation that is updated via a non-ui thread would be greatly appreciated. The solution and gist attached work great (values updated on any thread (ui or non-ui) no problem), it is just the DataBinding to a Form Control that is not.
Edit #1 - (Thank you Reza Aghaei)
I see where my question is a bit vague, here is the implementation and goal I am trying to accomplish.
First, I have the Form which handles the creation of a logic 'engine' which can run tasks (based on internal class methods as well as external method calls or events). So somewhere inside the Form class, I generate this logic 'engine' object (will call it GameEngine for this example).
// GameEngine initializes and provides the DynamicData (MyCustomObject)
// --> engine is defined via public or private field of (this) Form class
engine = new GameEngine();
// Create the binding
LabelTestCounter.Databindings.Add("Text", engine.Data, "TestValue", true, DataSourceUpdateMode.OnPropertyChanged);
Now in the GameEngine class, I instantiate the DynamicData (MyCustomObject)
public class GameEngine
{
public dynamic Data;
// Constructor
public GameEngine()
{
Data = new MyCustomObject();
// I would like to initialize the data here as ownership really
// belongs to the 'GameEngine' object, not the Form
engine.Data.TestValue = "Initial test value";
}
public void StartBusinessLogic()
{
// In reality, this would be a long-running loop that updates
// multiple values and performs business logic.
Task.Run(() => {
data.TestValue = "Another Text";
});
}
}
Note in this example above, the MyCustomObject is (currently) an exact copy of what Reza has provided in his gist in his answer below. In the blog post and the gist provided, I lean towards the 'Option 1' provided as I would like the DynamicData object (MyCustomObject), to be self-containing the logic for synchronization for portability purposes.
Another note, the GameEngine, outside of holding the DynamicData object in a property, should not care whether or not the UI thread is using it, the responsibility of synchronization should (in my mind) remain with the UI thread. With that said, the DynamicData object should be aware of cross threaded calls and handle them accordingly as needed.
Edit #2 - Original question reference update
In reference to:
I tried to implement the SynchronizedNotifyPropertyChanged solution
provided by Cody Barnes in the SO: INotifyPropertyChanged causes cross-thread error with no success.
When working with the original SO Dynamic object two way data binding, and the original solution (again thank you Reza), I attempted to implement the referenced 'wrapper' to overcome the problem with cross-threaded updates. However, the only way that I could get the above solution to work was when the properties were hard-coded into the class. When any attempts were made to use a dynamic object, the bindings would either update once and lose the binding or throw some kind of binding exception.
I hope this clarifies the original question a little bit better.
Edit #3 - Symbol not resolved
Not sure if this is a problem, as compilation is working, (and this may be Resharper, not sure as I don't recall the problem previously).
In 'MyCustomObject':
public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
var properties = new List<MyCustomPropertyDescriptor>();
foreach (var e in dictionary)
properties.Add(new MyCustomPropertyDescriptor(e.Key, (e.Value?.GetType()) ?? typeof(object)));
return new PropertyDescriptorCollection(properties.ToArray());
}
(e.Value?.GetType()) <-- GetType is showing 'Cannot resolve symbol 'GetType'.
however the code does compile without errors so I am not sure why/when exactly I started seeing this.
Edit #4 - Resolved Edit #3
No idea what caused the problem in Edit 3, but it grew into showing other errors (mysteriously) such as Cannot apply indexing with to an expression of type 'System.Collections.Generic.Dictionary', however, I did a Build -> Clean Solution and then closed the solution and reopened it in Visual Studio and the problem seemed to go away with that error highlighting in the editor (which I have been seeing a bit of strange behavior like that since I started playing with Resharper (EAP), so possibly early access bugs? but that problem is unrelated to this SO, the original SO has been resolved and the strange behavior in edit 3 will be better handled by JetBrains/Resharper Team rather than here at this point.
Edit #5 - Special Thanks
I hope this is not inappropriate (if it is, admins feel free to delete/edit this), however, I would like to send a special thank you to Reza Aghaei for all your help both here on SO as well as in the background. Reza, your blog, gists and other assistance with this ongoing problem has really helped both in solving the problem and helping me understand the reasons behind the solution.
To raise OnPropertyChanged from a non-UI thread in a way which updates the UI, you need to pass an instance of ISynchronizeInvoke to your implementation of ICustomTypeDescriptor:
ISynchronizeInvoke syncronzeInvoke;
public MyCustomObject(ISynchronizeInvoke value = null)
{
syncronzeInvoke = value;
}
Then on OnPropertyChanged use that ISynchronizeInvoke to Invoke when InvokeRequired:
private void OnPropertyChanged(string name)
{
var handler = PropertyChanged;
if (handler != null)
{
if (syncronzeInvoke != null && syncronzeInvoke.InvokeRequired)
syncronzeInvoke.Invoke(handler, new object[]
{ this, new PropertyChangedEventArgs(name) });
else
handler(this, new PropertyChangedEventArgs(name));
}
}
This way, the event will raise in UI thread when needed.
I am working in WPF with a MainWindow that has a (Prism) region "MainViewRegion". This switches based off the User's desired view and when it does, the MainWindow resizes to snap to the new dimensions of the embedded view.
I have some code to keep the window fully visible on the desktop after the Region switch. Here's the code:
private void WindowModeChange(string uri)
{
IRegion mviewRegion = regionManager.Regions[RegionNames.MainViewRegion];
if (mviewRegion == null) return;
regionManager.RequestNavigate(mviewRegion.Name, new Uri(uri, UriKind.Relative));
//Get the MainWindow instance from the container
var uc = container.Resolve<MainWindow>(InstanceNames.MainWindowView);
//Make sure the entire window is visible onscreen
ShiftWindowOntoScreenHelper.ShiftWindowOntoScreen(uc);
}
The issue is that the "uc" variable will always equal the MainWindow parameters from before the region change. The "uc" is always one step behind what I want, so the "snap-to" code is always off.
What am I missing?
Often when you have a piece of code that executes upon some event, and you need to ensure UI has already responded to that event to some degree, your best bet is to use a Dispatcher to defer the execution. Judging by the code you provided, the UI change is triggered by the regionManager.RequestNavigate call. Now I cannot point you to a piece of documentation that states that, but I know from experience that the framework will process this request asynchronously, i.e. the control will be returned to your method (allowing it to proceed) before all the work caused by this request is finished (hence your problem). That is (as far as I can tell) accomplished internally by the framework by using the said Dispatcher.
Depending on to what extent you need the framework to have processed the triggered change, you should use appropriate DispatcherPriority enum value to ensure certain things are done with once your code is executed. Basing on your question, I think the DispatcherPriority.Loaded is a good choice (from documentation the dispatcher will execute such code after the UI is rendered (which is crucial condition for you), but before any user input is processed). I personally tend to maximize the priority up to the point when it stops working (possibly avoiding some unexpected behavior caused by, for instance, user input).
So this modification to your code should be sufficient to accomplish your goal:
var uc = container.Resolve<MainWindow>(InstanceNames.MainWindowView);
uc.Dispatcher.InvokeAsync(() =>
ShiftWindowOntoScreenHelper.ShiftWindowOntoScreen(uc),
DispatcherPriority.Loaded);
Now I've noticed that you ultimately settled with Dispatcher.Invoke rather than Dispatcher.InvokeAsync - I guess it's ok in your case since it's the last instruction in your method, but generally the safe way is to use Dispatcher.InvokeAsync (I've personally experienced situations where Dispatcher.Invoke did not cut the mustard).
Thanks to Grx70 in the comments to my question, he gave me the solution. The body of the method now reads:
IRegion mviewRegion = regionManager.Regions[RegionNames.MainViewRegion];
if (mviewRegion == null) return;
mviewRegion.RequestNavigate(new Uri(uri, UriKind.Relative), (x =>
{
var uc = container.Resolve<MainWindow>(InstanceNames.MainWindowView);
uc.Dispatcher.Invoke(() => ShiftWindowOntoScreenHelper.ShiftWindowOntoScreen(uc), DispatcherPriority.Loaded);
}));
I am unsure as to why I had to call the Dispatcher in the callback parameter of the RequestNavigate(), but it won't work without it.
I'm quite new to Asynchronous and I understand some general concepts, but I cannot seem to fix couple of issues.
I have the following ReceiveCallback:
public static void ReceiveCallback(IAsyncResult AR)
{
Socket CurrentSocket = (Socket)AR.AsyncState;
int DataReceived = 0;
try
{
DataReceived = CurrentSocket.EndReceive(AR);
}
catch (SocketException)
{
CurrentSocket.Close();
return;
}
byte[] receivedBuffer = new byte[DataReceived];
Array.Copy(Buffer, receivedBuffer, DataReceived);
strReceived = Encoding.ASCII.GetString(receivedBuffer); // We are saving the latest receivedBuffer in a string.
new MainWindow().Process(); // We are accessing a function in the MainWindow class
receiveDone.Set();
CurrentSocket.BeginReceive(Buffer, 0, BufferSize, SocketFlags.None, ReceiveCallback, CurrentSocket);
}
Here's the "Process()" code:
public void Process()
{
lblReceived.Text = ClientSocket.strReceived; // Trying to set what we received in a label..
}
On the line: "new MainWindow().Process();",
I receive the following exception: "Additional information: The calling thread must be STA, because many UI components require this."
I've searched, and understood why it gives me the exception but several code did not work for me.
The label doesn't change, I know that I am creating a new instance of MainWindow and that's why nothing shows, but I'm seeking for example on how I can make the label change by using a new instance.
Unfortunately, without a good, minimal, complete code example there's no way to know enough context about your question to provide a precise answer.
But some general observations can be made:
Most important, if you need access to instance members of a class, it's because (or at least, should be becauseā¦it will always be, if the class is well-designed) there is already an instance of that class that you need to use. I.e. that instance has the state you need access to.
So creating a whole new instance of a class just because you couldn't otherwise access some instance member of the class (like the Process() method here) is always the wrong thing to do.
Instead, you need to provide access to that already-existing instance that has the state you need access to.
Just making a broad guess based on the bits and pieces of your code that were provided, I suppose that the ReceiveCallback() method is in fact declared in your MainWindow class. If this guess is correct, then the most obvious fix for the code is to simply make the ReceiveCallback() method non-static. I.e. remove static from the method declaration. Having done so, then all you need is to call Process() directly, instead of creating a new instance of MainWindow first.
Now, in doing so you may (or may not) find that providing the method as the parameter for the original I/O operation needs fixing. Again, since you didn't provide a good code example, it's not possible to say whether or how that would be done. But I mention it just so that you don't simply give up on the idea if it doesn't work as soon as you remove the static from the declaration.
Of course, my guess might be wrong. In which case, one option would be to provide the reference to your MainWindow instance as the state object for the I/O operation. Again, how exactly that would work is impossible to say without a good code example, but the basic idea is to pass it as the last argument to the Socket.BeginReceive() method (any overload), and then retrieve it from the IAsyncResult.AsyncState property in your ReceiveCallback() method.
Note: the above is only for addressing the specific exception you are getting, as creating a new MainWindow instance is simply guaranteed to be the wrong thing to do. Since the I/O operation most likely will complete outside the UI thread, you still have an issue related to dealing with that (e.g. needing to call Dispatcher.Invoke() on code that accesses the UI itself). But one step at a time. Let's fix the immediate problem before moving on to the next.
If none of the above seems helpful, then please fix your question so that it includes a good code example, with which an actual, precise answer can be provided.
I have a method that I'm trying to call from a unit test.
This method will in real life be run from a background thread. It uses some code to kick off in the invoke updates to the UI thread (using Application.Current.Dispatcher.BeginInvoke .... ).
However Application.Current is null when being called from the unit tests.
I don't really what to put an if (Application.Current !=null) around everything to fix.
Is there any other way around this?
_statusUpdates is an ObservableCollection
Below is the part of the code in the method I'm looking to test (it is more of an integration test than a unit test to be fair).
Application.Current.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, (EventHandler)delegate
{
_statusUpdates.Add(new StatusUpdate
{
DateTime = DateTime.Now,
Message = "Checking For Messages"
});
}, null, null);
The following code snippet works for me:
if (System.Windows.Application.Current == null)
{ new System.Windows.Application { ShutdownMode = ShutdownMode.OnExplicitShutdown }; }
IIRC, I had a problem where Application was null using a WPF control embedded in a WinForms application and that code snippet was suggested as a solution to the problem in another question on StackOverflow (sorry, can not find the source). It solves the same problem in unit tests (and I don't believe the ShutdownMode property needs to be explicitly set in that case).
As already stated, you simply won't have an Application class during unit tests.
That said, there's an issue here I think needs addressing - by having code that relies on a defined static property, in your case Application.Current.Dispatch, you are now very tightly coupled to the specific implementation of that class, namely the WPF Application class, where you do not need to be.
Even if you simply wrap the idea of "the current root dispatcher" in a Singleton-style class wrapper, now you have a way of decoupling yourself from the vagaries of the Application class and dealing directly with what you care about, a Dispatcher:
Note, there are MANY MANY ways to write this, I'm just putting up the simplest possible implementation; hence, I will not be doing any multithreaded safety checks, etc.
public class RootDispatcherFetcher
{
private static Dispatcher _rootDispatcher = null;
public static Dispatcher RootDispatcher
{
get
{
_rootDispatcher = _rootDispatcher ??
Application.Current != null
? Application.Current.Dispatcher
: new Dispatcher(...);
return _rootDispatcher;
}
// unit tests can get access to this via InternalsVisibleTo
internal set
{
_rootDispatcher = value;
}
}
}
Ok, now this implementation is only slightly better than before, but at least you now have finer control over access to the type and are no longer strictly dependent on the existence of an Application instance.
Use Dispatcher.CurrentDispatcher instead of Application.Current.Dispatcher
Gets the System.Windows.Threading.Dispatcher for the thread currently
executing and creates a new System.Windows.Threading.Dispatcher if one
is not already associated with the thread.
You will not have an Application object in a unit-test runner. These are usually "console" based applications that simply run and execute non-UI code ("units").
I suggest you don't use a unit test framework to test UI-specific information, I suggest a automated UI testing framework to do that.
So the issue here is that somewhere your Application object has to be created. So you need to find where the System.Windows.Application (or some descendent) class is being instantiated.
If the project was built from a template, then you'll probably find this class in the App.xaml file. You just need to make sure that this gets instantiated somehow. Else, search your entire project for an Application class, and then you'll have to instantiate it manually. Should fix it.
I have a windows form with a listview control. I have a selectedIndex changed event where i am performing some action. Through reflection I am trying to set the value of the list view.
But the event is not getting fired. Any help will be helpfull.
Edit
The event looks like
private void LV1_SelectedIndexChanged(object sender, EventArgs e)
{
if (LV1.SelectedItems.Count>0)
{
if (LV1.SelectedItems[0].Text.ToString() == "testing")
{
// Do some work.
}
}
}
I am using relection in another project and changing the selected item as follows
Assembly a = Assembly.LoadFrom(exePath);
Type formType = a.GetType(formName);
testForm = (Form)a.CreateInstance(formType.FullName);
if (testForm != null)
{
Type t1 = testForm.GetType();
FieldInfo fi = t1.GetField(controlName, flags);
object ctrl = fi.GetValue(testForm);
ListView l1 = (ListView)ctrl;
l1.Items[0].Selected = true;
}
Automating another application is fun howver not a trivial task. There's a few options but I guess most of them is out of scope for you. One would be to programatically take over the mouse and keyboard and trough those channels manage the program. Another way would be to manipulate memory, As I said neither are trivial to implement and very easily broken if the aplpication is updated.
I would suggest instead of trying to automate the application to look for infliction points. Are there any service endpoints you could automate and achieve the same result? any API or dll's used by the application you could use instead?
If you really have to automate the application there do exist several frameworks for doing that (usually build for testing purposes). The only one I can think off right now is made by Assima as is ment for training purposes.
I think your problem is here:
testForm = (Form)a.CreateInstance(formType.FullName);
You are creating a new instance of the form. I'm assuming your main project is an exe that runs an shows the form. Your second project is then another exe that runs and wants to change the selected item. By creating a new instance of the form you will be changing the selected item on the new form, not the old one.
What you need to do is somehow pass the form object over to the secondary project. possibly some static method that gets a singleton instance of the form maybe.
I'm still not entirely sure why you are using reflection, you could just give the second project a reference to the first.
The first question I'd ask is: why are you using reflection here? Just set the value through the public API. If you are messing underneath the public API, then yes: it is entirely possible that some events won't get fired.
Perhaps if you could show us exactly how you are doing this?