Revision: 39446
Initial Code
Initial URL
Initial Description
Initial Title
Initial Tags
Initial Language
at January 18, 2011 00:45 by kyrathaba
Initial Code
using System;
using System.Windows.Forms;
using System.Diagnostics;
using System.ComponentModel;
using System.Threading;
using System.IO;
namespace CrossThreadCallsToAControl {
public partial class Form1 : Form {
// This delegate enables asynchronous calls for setting
// the text property on a TextBox control.
delegate void SetTextCallback(string text);
// This thread is used to demonstrate both thread-safe and
// unsafe ways to call a Windows Forms control.
private Thread demoThread = null;
// This BackgroundWorker is used to demonstrate the
// preferred way of performing asynchronous operations.
private BackgroundWorker backgroundWorker1;
private delegate void DelegateOpenFile(String s);
DelegateOpenFile _openFileDelegate;
public const string appTitle = "My App Title";
public Form1() {
InitializeComponent();
this.StartPosition = FormStartPosition.CenterScreen;
this.Text = appTitle;
this.AllowDrop = true;
_openFileDelegate = new DelegateOpenFile(this.OpenFile);
backgroundWorker1 = new BackgroundWorker();
backgroundWorker1.RunWorkerCompleted +=
new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
}
private void Form1_Load(object sender, EventArgs e) {
}
private void Form1_MouseClick(object sender, MouseEventArgs e) {
switch (e.Button) {
case MouseButtons.Left:
break;
case MouseButtons.Right:
string path = Path.GetDirectoryName(Application.ExecutablePath);
System.Diagnostics.Process.Start("explorer.exe", path);
break;
default:
break;
}
}
private void Form1_KeyDown(object sender, KeyEventArgs e) {
if (e.KeyCode == Keys.Escape) { Application.Exit(); }
}
private void openToolStripMenuItem_Click(object sender, EventArgs e) {
OpenFileDialog openDlg = new OpenFileDialog();
openDlg.Filter = "Any File (*.*)|*.*";
openDlg.FileName = "";
openDlg.CheckFileExists = true;
openDlg.CheckPathExists = true;
if (openDlg.ShowDialog() != DialogResult.OK)
return;
OpenFile(openDlg.FileName);
}
private void OpenFile(string sFile) {
//insert appropriate file-opening code here...
MessageBox.Show("\"" + sFile + "\" will be opened.");
}
private void Form1_DragEnter(object sender, DragEventArgs e) {
if (e.Data.GetDataPresent(DataFormats.FileDrop))
e.Effect = DragDropEffects.Copy;
else
e.Effect = DragDropEffects.None;
}
private void Form1_DragDrop(object sender, DragEventArgs e) {
try {
Array a = (Array)e.Data.GetData(DataFormats.FileDrop);
if (a != null) {
// Extract string from first array element
// (ignore all files except first if number of files are dropped).
string s = a.GetValue(0).ToString();
// Call OpenFile asynchronously.
// Explorer instance from which file is dropped is not responding
// the entire time that the DragDrop handler is active, so we need to return
// immidiately (especially if OpenFile shows MessageBox).
this.BeginInvoke(_openFileDelegate, new Object[] { s });
this.Activate(); // in the case Explorer overlaps this form
}
}
catch (Exception ex) {
Trace.WriteLine("Error in DragDrop function: " + ex.Message);
// don't show MessageBox here - Explorer is waiting !
}
}
private void setTextUnsafeBtn_Click(object sender, EventArgs e) {
this.demoThread =
new Thread(new ThreadStart(this.ThreadProcUnsafe));
this.demoThread.Start();
}
// This method is executed on the worker thread and makes
// an unsafe call on the TextBox control.
private void ThreadProcUnsafe() {
this.textBox1.Text = "This text was set unsafely.";
}
private void setTextSafeBtn_Click(object sender, EventArgs e) {
this.demoThread =
new Thread(new ThreadStart(this.ThreadProcSafe));
this.demoThread.Start();
}
// This method is executed on the worker thread and makes
// a thread-safe call on the TextBox control.
private void ThreadProcSafe() {
this.SetText("This text was set safely.");
}
// This method demonstrates a pattern for making thread-safe
// calls on a Windows Forms control.
//
// If the calling thread is different from the thread that
// created the TextBox control, this method creates a
// SetTextCallback and calls itself asynchronously using the
// Invoke method.
//
// If the calling thread is the same as the thread that created
// the TextBox control, the Text property is set directly.
private void SetText(string text) {
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.textBox1.InvokeRequired) {
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else {
this.textBox1.Text = text;
}
}
private void setTextBackgroundWorkerBtn_Click(object sender, EventArgs e) {
this.backgroundWorker1.RunWorkerAsync();
}
// This event handler sets the Text property of the TextBox
// control. It is called on the thread that created the
// TextBox control, so the call is thread-safe.
//
// BackgroundWorker is the preferred way to perform asynchronous
// operations.
private void backgroundWorker1_RunWorkerCompleted(
object sender,
RunWorkerCompletedEventArgs e) {
this.textBox1.Text =
"This text was set safely by BackgroundWorker.";
}
}
}
Initial URL
Initial Description
demonstrates safe versus unsafe ways to make cross-thread calls
Initial Title
Safe vs. UnSafe cross-thread call
Initial Tags
Initial Language
C#