Status
Not open for further replies.

litewarez

Active Member
1,367
2008
1
0
heya guys

Im working on a C# Application and im having some issues with the ThreadSafe thingimabob.

When i try execute the a command i get the Thread not safe.

heres my Code!

PHP:
using System;
using System.Threading;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using ComponentFactory.Krypton.Toolkit;
using System.Windows.Forms;

namespace XXXXX
{
    public partial class Login : KryptonForm
    {

        public Login()
        {
            InitializeComponent();
        }

        private void Login_Load(object sender, EventArgs e)
        {
            //Hide Elements
            this.login_progress_bar.Visible = false;
        }

        private void ExitApp_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void doLogin(object sender, EventArgs e)
        {
            string u = login_username.Text;
            string p = login_password.Text;

            //Check for default values

            if (u.Length == 0 || p.Length == 0)
            {
                this.SetLoginStatus("Please fill out all login feilds");
                return;
            }
            this.LoginEnabled(false);
           /*
                      Removed all execution code here because its private application :) 
           */
        }

        //Handlers



        /*I Run the this.SetLoginStatus witch is located below, but it strikes an unsafe thread error*/
        private void j_XError(object sender, Exception ex) { this.SetLoginStatus("Incorrect Username or Password");}




        private void j_XAuth(object sender){/*ShowDialog("Authenticated: " + sender.ToString());*/}
        private void j_XWrite(object sender, string txt){if (txt == " ") return;/*ShowDialog("SEND: " + txt);*/}
        private void j_XRead(object sender, string txt){if (txt == " ") return;/*ShowDialog("RECV: " + txt);*/}
      
        //Dialog Box
        private void ShowDialog(string Message){MessageBox.Show(Message);}

        private void SetLoginStatusTest(string message)
        {
            label1.Text = message;
        }

        private void SetLoginStatus(string message)
        {
            label1.Text = message;
        }

        private void LoginEnabled(bool status) 
        {
            login_username.Enabled = login_password.Enabled = login_button.Enabled = status;
        }

        //Menu Actions
        private void OptionsMenuOpen(object sender, EventArgs e)
        {
            Settings Settings = new Settings();
            Settings.Show();
        }
    }
}

Ok so i have j_XError above witch calls the SetLoginStatus But i get an error about not being Thread Safe.

Can someone explain to me whats going in
 
12 comments
Ok so because its an event the event is being executed by another object from another name-space and therefore it cant cross thread ?
 
No. Whatever is calling your method is doing so from a thread that is not the GUI thread. It has little to do with objects or namespaces. It can't help you any further since you use non standard controls.
 
Okay.

For your information heres wahts going on

I have a library that's i use to contact a Jabber Server, and i Assign callbacks / events for Successful Connection, Login Failed etc etc... Its the methods that i tell it to call that has has problem.

What ive done is create a separate class to hold the Methods that will be called on the event attached to it... I have to learn about the threading to get the Callbacks class to be able to modify the the Form class.. I think

So now i have defined my callbacks Class in my Form Class like so:

PHP:
private XXXX.JabberCallbacks.JabberCallbacks _JabberCallbacks = new XXXX.JabberCallbacks.JabberCallbacks();

And then when the login button is click it will run a method within the login Class, After basic input validation i assign the callbacks like So

PHP:
Jabber.OnError += new bedrock.ExceptionHandler(_JabberCallbacks.OnError);

So that _JabberCallbacks.OnError will be called if an error accrues.

On the _JabberCllbacks class heres the OnError Method:

PHP:
public void OnError(object sender, Exception ex)
        {
              //Here i need to be able to set a Label in the Login Form :/
        }
 
lambda + yourForm.Invoke() = solution
As I said in the first post ;).

So, this
PHP:
        private void SetLoginStatus(string message)
        {
            label1.Text = message;
        }
becomes
PHP:
        private void SetLoginStatus(string message)
        {
            this.Invoke(() => this.label1.Text = message);
        }

Also, give your controls meaningfull names lol. lblTitle > label1. txtPassword > textbox1.
 
With your code i still get a few errors witch im unsure of:

Code:
Error	1
Cannot convert lambda expression to type 'System.Delegate' because it is not a delegate type
C:\Users\XXXX\documents\visual studio 2010\Projects\XXXX\XXXX\Login.cs

Edit, I Also changed the Private to Public so i can call it from another Class
 
OK that seemed to have fixed the errors but im confused about whats going on!


Ok so i have this line:
PHP:
//From the main form:DoLogin()
Jabber.OnError += new bedrock.ExceptionHandler(_JabberCallbacks.OnError);

Witch then will run the following method:

PHP:
public void OnError(object sender, Exception ex)
{
    //Here i want to run the follwing
    Login.SetLoginStatus("Error: " + ex.ToString());

   /*
        The line above strings the following error!
        An object reference is required for the non-static field, method, or property 'XXXX.Login.SetLoginStatus(string)'

   */
}


Witch is located in the main form
PHP:
public void SetLoginStatus(string message)
{
    var a = new Action(() => this.label1.Text = message);
    this.Invoke(a);
}
 
whats confusing me is the way you have to cross just lots of different classes.

I c ant really do a flow chart but

Code:
(Main Class) -> (Jabber Class) -> (Callbacks Class) -> (Main Class) -> [SetLoginStatus]

I dont understand why it cant follow the following route
Code:
(Main Class) -> (Jabber Class) -> (Main Class) -> [SetLoginStatus]
 
C# is a 110% OO language, unlike PHP. C# has events. Everything is C# is an object. In other words in OOP it is normal to be calling classes from classes. However, if something gets confusing about the flow of the program that is most likely due to a poor design or the use of crappy libraries.
 
"Thread cannot access object in which it was not created on"

That kind of error, or whatever it actually comes up with means exactly that. The thread that is trying to access a textbox, for example, that the thread did not specifically create itself, cannot access it simply because another thread may be doing something with it and mess it all up. So you have to invoke that textbox and say "hey, whats your status as of now". I showed you how to create instances of objects in a few of my sources, which is why i tryed to explain how to do things like that - its so much easier. Invoking objects is quite easy and actually makes a lot of sense once you get into the routine of it.

Take a look at my multi-threading example (attempt :P) and see if you can get any idea in how to go about doing such things:

http://www.wjunction.com/showthread.php?t=37330

Edit: Making objects out of things and making them re-useable, things like that are really useful here. Make a delegate and make it useful. A general status delegate for example that will be constantly used is a good idea. So for example have:
PHP:
public delegate void GeneralStatusDelegate(string status, int progress, int maxProgress);
        private void GeneralStatus(string status, int progress, int maxProgress)
        {
            toolStripStatusLabel1.Text = status;
            toolStripProgressBar1.Maximum = maxProgress;
            toolStripProgressBar1.Value = progress;

            if (progress == maxProgress || progress == 0)
                toolStripProgressBar1.Visible = false;
            else
                toolStripProgressBar1.Visible = true;
        }

This will be very useful to invoke as you can see. We can set a string status, a current progress of the progressbar and a MaxProgress. very useful :)
 
Status
Not open for further replies.
Back
Top