"Peter Duniho" <NpOeStPeAdM@nnowslpianmk.comwrote in message
news:op.uiunnlsk8jd0ej@petes-computer.local...
Quote:
On Fri, 10 Oct 2008 22:23:06 -0700, tshad <tfs@dslextreme.comwrote:
>
Quote:
>[...]
>I get the error:
> Cross-thread operation not valid: Control 'btnExit' accessed
>from a thread other than the thread it was created on.
>>
>I am trying to find out how to access the controls on the Form from
>either
>the same class or a different class (which was why we were passing
>"this" to
>the other class).
>>
>This all works fine until you put it in a thread.
>
That's because you need to use Control.Invoke() or Control.BeginInvoke()
to execute the code that actually has to touch the control itself.
>
The other reply doesn't really address this. That reply is not a lot
different from your own attempt to solve the issue with a property, in
that it's just an alternate route to the same code, ultimately with the
same problem: it will try to interact with the control from a thread other
than the one that owns that control.
>
Without a concise-but-complete code sample to work with, it's difficult to
propose a precise change for your particular scenario. But, as an
example, you might modify your IStatusDisplay.Status property so that it
looks like this:
[snip]
Ok, here is a stripped down sample that consists of 3 buttons, a textbox,
statusbar and toolStripStatusLabel.
I have 2 files (form1 and Maintenance). In form1 I am calling a function in
Maintenance that just writes to the textbox and the toolStripStatusLabel.
The first button calls the function without a thread and the second with a
thread.
I also have a this.Refresh() in the code to display on the page correctly
when not running in the thread, but in the thread it gives me the error:
Cross-thread operation not valid: Control 'Form1' accessed from a thread
other than the thread it was created on.
If I comment it out, and run the threading, I get the following when the
program tries to write to the textbox (Status) from the Maintenance
function:
display.Status += file + Environment.NewLine;
Calls this to set the value
set
{
Status.Text = value;
}
And get the error:
Cross-thread operation not valid: Control 'Status' accessed from a
thread other than the thread it was created on.
but I don't get the error when setting the toolStripStatusLabel from the
Maintenance function:
display.StatusBar = "Now Processing... " + file;
Why is that? They are both using the "this" that was passed.
Just trying to understand the different ways to do this so I can choose the
right way in other situations as well.
The 3 files in my project are:
form1.cs
************************************************** **
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 System.Windows.Forms;
namespace ControlAccessAcrossClasses
{
public partial class Form1 : Form, IStatusDisplay
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
toolStripStatusLabel1.Text = "This is a test";
}
#region IStatusDisplay Members
string IStatusDisplay.Status
{
get
{
return Status.Text;
}
set
{
Status.Text = value;
}
}
string IStatusDisplay.StatusBar
{
get
{
return toolStripStatusLabel1.Text;
}
set
{
toolStripStatusLabel1.Text = value;
//this.Refresh();
}
}
#endregion
private void WithoutThreadButton_Click(object sender, EventArgs e)
{
Maintenance.CheckAll(this);
}
private void WithThreadButton_Click(object sender, EventArgs e)
{
Thread oThread = new Thread(new ThreadStart(CallWithThread));
oThread.Start();
}
private void CallWithThread()
{
Maintenance.CheckAll(this);
}
private void Exit_Click(object sender, EventArgs e)
{
Application.Exit();
}
}
}
************************************************** *************
maintenance.cs
************************************************** ************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ControlAccessAcrossClasses
{
class Maintenance
{
public static void CheckAll(IStatusDisplay display)
{
String file = "12345.txt";
display.StatusBar = "Now Processing... " + file;
display.Status += file + Environment.NewLine;
}
}
public interface IStatusDisplay
{
string Status { get; set; }
string StatusBar { get; set; }
}
}
************************************************** ************
And the form1.designer.cs
************************************************** ***********
namespace ControlAccessAcrossClasses
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be
disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.Status = new System.Windows.Forms.TextBox();
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
this.toolStripStatusLabel1 = new
System.Windows.Forms.ToolStripStatusLabel();
this.WithThreadButton = new System.Windows.Forms.Button();
this.WithoutThreadButton = new System.Windows.Forms.Button();
this.Exit = new System.Windows.Forms.Button();
this.statusStrip1.SuspendLayout();
this.SuspendLayout();
//
// Status
//
this.Status.Location = new System.Drawing.Point(30, 12);
this.Status.Multiline = true;
this.Status.Name = "Status";
this.Status.Size = new System.Drawing.Size(364, 286);
this.Status.TabIndex = 0;
//
// statusStrip1
//
this.statusStrip1.Items.AddRange(new
System.Windows.Forms.ToolStripItem[] {
this.toolStripStatusLabel1});
this.statusStrip1.Location = new System.Drawing.Point(0, 347);
this.statusStrip1.Name = "statusStrip1";
this.statusStrip1.Size = new System.Drawing.Size(495, 22);
this.statusStrip1.TabIndex = 1;
this.statusStrip1.Text = "statusStrip1";
//
// toolStripStatusLabel1
//
this.toolStripStatusLabel1.Name = "toolStripStatusLabel1";
this.toolStripStatusLabel1.Size = new System.Drawing.Size(0,
17);
//
// WithThreadButton
//
this.WithThreadButton.Location = new System.Drawing.Point(187,
316);
this.WithThreadButton.Name = "WithThreadButton";
this.WithThreadButton.Size = new System.Drawing.Size(90, 23);
this.WithThreadButton.TabIndex = 2;
this.WithThreadButton.Text = "With Thread";
this.WithThreadButton.UseVisualStyleBackColor = true;
this.WithThreadButton.Click += new
System.EventHandler(this.WithThreadButton_Click);
//
// WithoutThreadButton
//
this.WithoutThreadButton.Location = new System.Drawing.Point(30,
316);
this.WithoutThreadButton.Name = "WithoutThreadButton";
this.WithoutThreadButton.Size = new System.Drawing.Size(114,
23);
this.WithoutThreadButton.TabIndex = 3;
this.WithoutThreadButton.Text = "Without Thread";
this.WithoutThreadButton.UseVisualStyleBackColor = true;
this.WithoutThreadButton.Click += new
System.EventHandler(this.WithoutThreadButton_Click );
//
// Exit
//
this.Exit.Location = new System.Drawing.Point(318, 316);
this.Exit.Name = "Exit";
this.Exit.Size = new System.Drawing.Size(75, 23);
this.Exit.TabIndex = 4;
this.Exit.Text = "Exit";
this.Exit.UseVisualStyleBackColor = true;
this.Exit.Click += new System.EventHandler(this.Exit_Click);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(495, 369);
this.Controls.Add(this.Exit);
this.Controls.Add(this.WithoutThreadButton);
this.Controls.Add(this.WithThreadButton);
this.Controls.Add(this.statusStrip1);
this.Controls.Add(this.Status);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.statusStrip1.ResumeLayout(false);
this.statusStrip1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.TextBox Status;
private System.Windows.Forms.StatusStrip statusStrip1;
private System.Windows.Forms.ToolStripStatusLabel
toolStripStatusLabel1;
private System.Windows.Forms.ToolStripStatusLabel
toolStripStatusLabel2;
private System.Windows.Forms.Button WithThreadButton;
private System.Windows.Forms.Button WithoutThreadButton;
private System.Windows.Forms.Button Exit;
}
}
************************************************** ************
Not sure why there are 2 "partial class form1" classes.
Thanks,
Tom