I have set the textbox to public so that another form can access it but when i run it in debug mode with the following line it gives me exception so it doesn't store correct directory.
For example:
If I enter D:\newfolder it gives me D:\\newfolder. Why does it add the extra \.

Here's the exception:
An exception 'Microsoft.VisualStudio.Debugger.Runtime.CrossThreadMessagingException' occurred

Here's the line where the exception occurs.

Choose is a class in the same namespace as the method which contains this string.
The method is in a different class than the choose class.
txtbxTargetDir is the name of the textbox.

string targetPath = StaticFormInstances.choose.txtbxTargetDir.Text;

Dani AI

Generated

Two separate issues are visible in the thread. The "D:\newfolder" appearance is the debugger showing a C#-escaped representation of the string; the runtime string used by File/Directory APIs contains a single backslash. As already noted, the '@' prefix only affects string literals in source code, not values entered at runtime. The crash (CrossThreadMessagingException) is a separate problem: the BackgroundWorker DoWork handler runs on a thread-pool thread and is trying to read a WinForms control property (TextBox.Text) that belongs to the UI thread. That direct cross-thread access causes the exception.

Two safe fixes are common and reliable:

  • Capture the path on the UI thread before the background work starts and pass it into the worker. Example pattern:
// start worker from the UI thread, pass the text as an argument
bckgrdInstallDll.RunWorkerAsync(StaticFormInstances.choose.txtbxTargetDir.Text);

// inside DoWork
string targetPath = e.Argument as string;
  • Marshal the read back to the UI thread with Invoke so the control is accessed on its creating thread:
string GetTargetPath()
{
    if (StaticFormInstances.choose.InvokeRequired)
        return (string)StaticFormInstances.choose.Invoke(new Func<string>(() => StaticFormInstances.choose.txtbxTargetDir.Text));
    return StaticFormInstances.choose.txtbxTargetDir.Text;
}

Additional notes tied to the posted code: reading a control after it has been Hidden or Disposed can fail, so prefer storing the chosen path in a plain string property on the ChooseDirectory form at selection time (no control access needed later). Avoid relying on static form instances for program state if possible. Also fix the progress math (integer division): compute percent with int progress = (fileNumber * 100) / totalNumberOfFiles; so progress doesn't stay zero until the end. These changes address both the escaped-backslash confusion (debugger view) and the cross-thread exception seen in 's DoWork handler; 's substring idea only removes characters and does not solve the threading issue.

Recommended Answers

All 13 Replies

try

string targetPath ="@" + StaticFormInstances.choose.txtbxTargetDir.Text;

that doesn't work, it just adds the @ sign in front of the string and still keeps 2 \\

the extra backslash is an escape character; it is used at the start of an escape sequence. An escape sequence is a series of characters which the compiler reads and converts into somethign else. For instance \n becomes a newline character. To tell the compiler that the '\' is to be treated as a plain character you have to escape it. Hence the double \. If you display the string in a textbox or a messagebox it should only show a single one (the debugger will show you the extra one when you use a watch).
The trick of using an '@' wont work the way shown above. It CAN be used to declare a literal string. eg string str = @"this backslash \ is just a literal character"; . By putting an @ before the string you tell the compiler that none of the characters are escape sequences, they are just plain old characters :)

label1.Text = label1.Text.Substring(0, label1.Text.IndexOf(@"\")) + label1.Text.Substring(label1.Text.IndexOf(@"\")+1, label1.Text.Length-(label1.Text.IndexOf(@"\"))-1);

Here this should give you a fix.

It will basically remove one of the slashes.

I still get the same exception. I think its because I am trying to access it in multiple forms. Maybe???
Btw I have each form set up as static so that I can add back button to it.


Heres the exception:
at Microsoft.VisualStudio.Debugger.Runtime.Main.ThrowCrossThreadMessageException(String formatString) at System.Windows.Forms.SafeNativeMethods.GetWindowTextLength(HandleRef hWnd) at System.Windows.Forms.Control.get_WindowText() at System.Windows.Forms.TextBoxBase.get_WindowText() at System.Windows.Forms.Control.get_Text() at System.Windows.Forms.TextBox.get_Text()

Please help.

hmm, what does the targetPath equal to right before the line of error?

try

MessageBox.Show(targetPath);

right before the line error.

Here is my code

public partial class InstallingDlls : Form
    {
        public InstallingDlls()
        {
            InitializeComponent();
            bckgrdInstallDll.RunWorkerAsync();
        }

        private void bckgrdInstallDll_DoWork(object sender, DoWorkEventArgs e)
        {
            //string text = StaticFormInstances.choose.txtbxTargetDir.Text.Substring(0, StaticFormInstances.choose.txtbxTargetDir.Text.IndexOf(@"\")) + StaticFormInstances.choose.txtbxTargetDir.Text.Substring(StaticFormInstances.choose.txtbxTargetDir.Text.IndexOf(@"\") + 1, StaticFormInstances.choose.txtbxTargetDir.Text.Length - (StaticFormInstances.choose.txtbxTargetDir.Text.IndexOf(@"\")));


            string fileName = "test.txt";
            string targetPath = StaticFormInstances.choose.txtbxTargetDir.Text;
            string sourcePath = @"\\il93fil48\3GSM\release\testapplication_REL_01_00_09\bin";

            //Use Path Class to manipulate file and directory paths
            string sourceFile = System.IO.Path.Combine(sourcePath, fileName);
            string destFile = System.IO.Path.Combine(targetPath, fileName);

            //Create a new target folder if it doesn't exist
            if (!System.IO.Directory.Exists(targetPath))
            {
                System.IO.Directory.CreateDirectory(targetPath);
            }


            if (System.IO.Directory.Exists(sourcePath))
            {
                string[] files = System.IO.Directory.GetFiles(sourcePath);

                //calculate total number of files in source
                int totalNumberOfFiles = files.Length;

                //current file number
                int fileNumber = 0;

                //copy the files and overwrite destination files if they already exist
                foreach (string s in files)
                {
                    //increase file number by 1
                    fileNumber++;

                    //Use static Path methods to extract only the file name from the path.
                    fileName = System.IO.Path.GetFileName(s);
                    destFile = System.IO.Path.Combine(targetPath, fileName);
                    System.IO.File.Copy(s, destFile, true);

                    //calculate progess out of base of 100
                    int ProgressPercentage = (fileNumber/totalNumberOfFiles)*100;

                    //update the progress bar
                    bckgrdInstallDll.ReportProgress(ProgressPercentage);
                }
            }
            else
            {
                Console.WriteLine("Source path does not exist");
            }
        }

        private void bckgrdInstallDll_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            prgBarDll.Value = e.ProgressPercentage;
        }

        private void bckgrdInstallDll_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            StaticFormInstances.database = new Database();
            StaticFormInstances.database.Show();
            StaticFormInstances.dll.Hide();
        }
    }

The error you are getting is a thread related exception. Can you post your code so we can see what it is you are doing.

If you are accessing controls from a thread you will need to invoke a delegate. You cannot directly access controls form another thread. Check out the and see if that helps any.

I am not trying to update my value in another thread, I am trying to access it.

The principle is the same; you need to invoke a delegate method to retreive the value as you cannot directly access the control.
The example accepts a string as input but returns no value. Heres part one of reversing the process:

// Returns the textbox text.
private string UpdateText()
{
  // Send textbox text back to calling method
  return m_TextBox.Text;
}

If you have troubles with the rest, post what you ahve and we'll guide you through it

It doesn't seem to work. Compile error.

namespace Welcome
{
    public delegate string ReturnText();
    public partial class InstallingDlls : Form
    {
        public InstallingDlls()
        {
            InitializeComponent();
            bckgrdInstallDll.RunWorkerAsync();
        }

        private void bckgrdInstallDll_DoWork(object sender, DoWorkEventArgs e)
        {
            StaticFormInstances.dll.Invoke(new ReturnText(this.UpdateText));

            string fileName = "test.txt";
            string targetPath = StaticFormInstances.choose.txtbxTargetDir.Text;
            string sourcePath = @"\\il93fil48\3GSM\release\testapplication_REL_01_00_09\bin";

            //Use Path Class to manipulate file and directory paths
            string sourceFile = System.IO.Path.Combine(sourcePath, fileName);
            string destFile = System.IO.Path.Combine(targetPath, fileName);

            //Create a new target folder if it doesn't exist
            if (!System.IO.Directory.Exists(targetPath))
            {
                System.IO.Directory.CreateDirectory(targetPath);
            }


            if (System.IO.Directory.Exists(sourcePath))
            {
                string[] files = System.IO.Directory.GetFiles(sourcePath);

                //calculate total number of files in source
                int totalNumberOfFiles = files.Length;

                //current file number
                int fileNumber = 0;

                //copy the files and overwrite destination files if they already exist
                foreach (string s in files)
                {
                    //increase file number by 1
                    fileNumber++;

                    //Use static Path methods to extract only the file name from the path.
                    fileName = System.IO.Path.GetFileName(s);
                    destFile = System.IO.Path.Combine(targetPath, fileName);
                    System.IO.File.Copy(s, destFile, true);

                    //calculate progess out of base of 100
                    int ProgressPercentage = (fileNumber/totalNumberOfFiles)*100;

                    //update the progress bar
                    bckgrdInstallDll.ReportProgress(ProgressPercentage);
                }
            }
            else
            {
                Console.WriteLine("Source path does not exist");
            }
        }

        private void bckgrdInstallDll_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            prgBarDll.Value = e.ProgressPercentage;
        }

        private void bckgrdInstallDll_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            StaticFormInstances.database = new Database();
            StaticFormInstances.database.Show();
            StaticFormInstances.dll.Hide();
        }
    }
}

namespace Welcome
{
    public partial class ChooseDirectory : Form
    {
        public ChooseDirectory()
        {
            InitializeComponent();
        }

        private void btnNext_Click(object sender, EventArgs e)
        {
            StaticFormInstances.choose.Hide();
            StaticFormInstances.loc = new Location();
            StaticFormInstances.loc.Show();
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            StaticFormInstances.wel.Dispose();
            StaticFormInstances.choose.Dispose();
        }

        private string UpdateText()
        {
            //send textbox text back to calling method
            return StaticFormInstances.choose.txtbxTargetDir.Text;
        }
    }
}

Can you post your project? Im having troubles replicating the issue :/
If you click "Use Advanced Editoer" there is an attachments button at the top of the box where you can add a zipped copy of your folder.
If i can run your code i may be ablet o find the problem :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.