Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
DotNETFrameworkNotesForProfessionals.pdf
Скачиваний:
32
Добавлен:
20.05.2023
Размер:
1.82 Mб
Скачать

Chapter 39: Threading

Section 39.1: Accessing form controls from other threads

If you want to change an attribute of a control such as a textbox or label from another thread than the GUI thread that created the control, you will have to invoke it or else you might get an error message stating:

"Cross-thread operation not valid: Control 'control_name' accessed from a thread other than the thread it was created on."

Using this example code on a system.windows.forms form will cast an exception with that message:

private void button4_Click(object sender, EventArgs e)

{

Thread thread = new Thread(updatetextbox); thread.Start();

}

private void updatetextbox()

{

textBox1.Text = "updated"; // Throws exception

}

Instead when you want to change a textbox's text from within a thread that doesn't own it use Control.Invoke or Control.BeginInvoke. You can also use Control.InvokeRequired to check if invoking the control is necessary.

private void updatetextbox()

{

if (textBox1.InvokeRequired)

textBox1.BeginInvoke((Action)(() => textBox1.Text = "updated"));

else

textBox1.Text = "updated";

}

If you need to do this often, you can write an extension for invokeable objects to reduce the amount of code necessary to make this check:

public static class Extensions

{

public static void BeginInvokeIfRequired(this ISynchronizeInvoke obj, Action action)

{

if (obj.InvokeRequired) obj.BeginInvoke(action, new object[0]);

else

action();

}

}

And updating the textbox from any thread becomes a bit simpler:

private void updatetextbox()

{

textBox1.BeginInvokeIfRequired(() => textBox1.Text = "updated");

}

GoalKicker.com – .NET Framework Notes for Professionals

125

Be aware that Control.BeginInvoke as used in this example is asynchronous, meaning that code coming after a call to Control.BeginInvoke can be run immedeately after, whether or not the passed delegate has been executed yet.

If you need to be sure that textBox1 is updated before continuing, use Control.Invoke instead, which will block the calling thread until your delegate has been executed. Do note that this approach can slow your code down significantly if you make many invoke calls and note that it will deadlock your application if your GUI thread is waiting for the calling thread to complete or release a held resource.

GoalKicker.com – .NET Framework Notes for Professionals

126

Chapter 40: Process and Thread a nity setting

Parameter

Details

integer that describes the set of processors on which the process is allowed to run. For example, on a 8 a nity processor system if you want your process to be executed only on processors 3 and 4 than you choose

a nity like this : 00001100 which equals 12

Section 40.1: Get process a nity mask

public static int GetProcessAffinityMask(string processName = null)

{

Process myProcess = GetProcessByName(ref processName);

int processorAffinity = (int)myProcess.ProcessorAffinity; Console.WriteLine("Process {0} Affinity Mask is : {1}", processName,

FormatAffinity(processorAffinity));

return processorAffinity;

}

public static Process GetProcessByName(ref string processName)

{

Process myProcess;

if (string.IsNullOrEmpty(processName))

{

myProcess = Process.GetCurrentProcess(); processName = myProcess.ProcessName;

}

else

{

Process[] processList = Process.GetProcessesByName(processName); myProcess = processList[0];

}

return myProcess;

}

private static string FormatAffinity(int affinity)

{

return Convert.ToString(affinity, 2).PadLeft(Environment.ProcessorCount, '0');

}

}

Example of usage :

private static void Main(string[] args)

{

GetProcessAffinityMask();

Console.ReadKey();

}

//Output:

//Process Test.vshost Affinity Mask is : 11111111

Section 40.2: Set process a nity mask

public static void SetProcessAffinityMask(int affinity, string processName = null)

GoalKicker.com – .NET Framework Notes for Professionals

127

{

Process myProcess = GetProcessByName(ref processName);

Console.WriteLine("Process {0} Old Affinity Mask is : {1}", processName, FormatAffinity((int)myProcess.ProcessorAffinity));

myProcess.ProcessorAffinity = new IntPtr(affinity); Console.WriteLine("Process {0} New Affinity Mask is : {1}", processName,

FormatAffinity((int)myProcess.ProcessorAffinity));

}

Example of usage :

private static void Main(string[] args)

{

int newAffinity = Convert.ToInt32("10101010", 2); SetProcessAffinityMask(newAffinity);

Console.ReadKey();

}

//Output :

//Process Test.vshost Old Affinity Mask is : 11111111

//Process Test.vshost New Affinity Mask is : 10101010

GoalKicker.com – .NET Framework Notes for Professionals

128