[Reprint] multi-thread explanation for implementing security in Windows Forms

Source: Internet
Author: User
Go to original address

Preface

In our applicationProgramDuring the development process, there are often some problems that need to be solved using multithreading technology. This article explains some main problems related to multithreading through several sample programs.

CEO task operations

Many types of applications require long-term operations, such as executing a print task and requesting a web service call. In this case, the user usually transfers other tasks to wait for the task to be completed, and wants to monitor the progress of the task at any time.

The followingCodeThe sample snippet shows how the user interface is updated when a long task is executed.

// Display progress bar
Void Showprogress ( Int Totalstep, Int Currentstep)
{
_ Progress. Maximum = Totalstep;
_ Progress. Value = Currentstep;
}

// Execute task
Void Runtask ( Int Seconds)
{
// Display progress every 1/4 seconds
For ( Int I =   0 ; I < Seconds *   4 ; I ++ )
{
Thread. Sleep ( 250 );

// display progress bar
showprogress (seconds * 4 , I + 1 );
}< BR >}

Private Void_ Btnrun_click (ObjectSender, system. eventargs E)
{
Runtask (convert. toint32 (_ txtsecond. Value ));
}

When we run the above program, there is no problem throughout the long task process. So there is no problem? When we switch the application to do other things and then switch back, the problem will happen! The main form will see the following situation:

This problem will certainly happen because our current application is single-threaded. Therefore, when the thread executes a task, it cannot re-draw the user interface at the same time.

Why does the problem occur after we switch the application? This is because when you switch the current application to the background and switch back to the foreground, we need to re-draw the entire user interface. However, the application is executing the task and there is no time to process the re-painting of the user interface.

How to solve the problem? We need to run long tasks in the background to free up the user interface threads, so we need another thread.

Asynchronous thread operation

The click processing of the buttons in the above program is as follows:

Private   Void _ Btnrun_click ( Object Sender, system. eventargs E)
{
Runtask (convert. toint32 (_ txtsecond. Value ));
}

Recall the cause of the above problem until the runtask is returned after execution, and the click processing function cannot be returned. This means that the user interface cannot process the re-painting event or any other event. One solution is to create another thread. The code snippet is as follows:

Using System. Threading;

Private Int_ Seconds;

//Task execution worker thread entry point
VoidRuntaskthreadstart ()
{
Runtask (_ seconds );
}

//Eliminate user interface thread blocking by creating a working thread
Private Void_ Btnrun_click (ObjectSender, system. eventargs E)
{
_ Seconds=Convert. toint32 (_ txtsecond. value );

Thread runtaskthread= NewThread (NewThreadstart (runtaskthreadstart ));

Runtaskthread. Start ();
}

Now, we no longer need to wait until runtask execution is complete before returning from the click event. We have created a new working thread and started it to work and run.

Runtaskthread. Start (); schedules and immediately returns the newly created worker thread, allowing the user interface thread to regain control and execute its own work. Now, if the user switches the application again, because the worker thread executes the task in his own space, the user interface thread is freed to process various events including user interface re-painting, the problem we encountered above is solved.

Delegated asynchronous call

In the code above, we noticed that we didn't pass any parameters to the worker thread entry point (runtaskthreadstart). We passed parameters to the worker thread by declaring the _ seconds field of a form class. In an application, it is also very painful to directly pass parameters to the worker thread.

How can we improve it? We can use Delegation for asynchronous calls. Delegation supports parameter passing. In this way, the problem we just encountered is eliminated, so that we can eliminate additional field declarations and additional working thread functions.

If you are not familiar with delegation, you can simply think of it as a safe function pointer. Use a delegated asynchronous call. The code snippet is as follows:

// Task execution delegate statement
Delegate   Void Runtaskdelegate ( Int Seconds );

// solve the parameter transfer problem by creating a DeleGate
private void _ btnrun_click ( Object sender, system. eventargs e)
{< br> runtaskdelegate runtask = New runtaskdelegate (runtask );

// delegate synchronous call method
runtask (convert. toint16 (_ txtsecond. value);
}

// solve the parameter passing problem by creating a delegate, use a delegated asynchronous call to eliminate blocking of user interface threads
private void _ btnrun_click ( Object sender, system. eventargs e)
{< br> runtaskdelegate runtask = New runtaskdelegate (runtask );

//Delegated asynchronous call Method
Runtask. begininvoke (convert. toint16 (_ txtsecond. value ),Null,Null);
}

Multithreading Security

So far, we have solved the problem of long tasks and the trouble of passing parameters. But have we solved all the problems? The answer is no.

We know that there is a mandatory principle in Windows programming, that is, the form cannot be operated in any thread other than the creation thread of a form.

The preceding program has the following problem: the worker thread modifies the properties of the progress bar on the user interface in the showprogress method. Why is the program running normal without any problem?

The problem does not occur because the current Windows XP operating system has a very robust solution to this type of problem, which allows us to avoid the problem. However, our current program cannot ensure that it can run normally in other operating systems!
The real solution is to recognize the problem and avoid it in the program.

How can we avoid the security problem of multi-threaded form resource access? In fact, it is very simple. There are two methods:

One way is to delegate access to user interface resources regardless of whether the thread is a user interface thread;

Another method is to have an invokerequired attribute in each Windows Forms user interface class, which is used to identify whether the current thread can directly access form resources. You only need to check the value of this attribute. You can access the corresponding resources only when you allow direct access to the form resources. Otherwise, you need to access the resources through delegation.

The code snippet using the first secure method is as follows:

// Delegate statement for displaying progress bars
Delegate   Void Showprogressdelegate ( Int Totalstep, Int Currentstep );

// Display progress bar
Void Showprogress ( Int Totalstep, Int Currentstep)
{
_ Progress. Maximum = Totalstep;
_ Progress. Value = Currentstep;
}

// Task execution delegate statement
Delegate   Void Runtaskdelegate ( Int Seconds );

// Execute task
Void Runtask ( Int Seconds)
{
Showprogressdelegate showprogress =   New Showprogressdelegate (showprogress );

// Display progress every 1/4 seconds
For ( Int I =   0 ; I < Seconds *   4 ; I ++ )
{
Thread. Sleep ( 250 );

//Display progress bar
This. Invoke (showprogress,New Object[] {Seconds* 4, I+ 1});
}
}

The code snippet using the second security method is as follows:

// Delegate statement for displaying progress bars
Delegate   Void Showprogressdelegate ( Int Totalstep, Int Currentstep );

// Display progress bar
Void Showprogress ( Int Totalstep, Int Currentstep)
{
If (_ Progress. invokerequired)
{
Showprogressdelegate showprogress =   New Showprogressdelegate (showprogress );

// In order to prevent the working thread from being blocked, the asynchronous call delegate is used.
This . Begininvoke (showprogress, New   Object [] {Totalstep, currentstep });
}
Else
{
_ Progress. Maximum = Totalstep;
_ Progress. Value = Currentstep;
}
}

//Task execution delegate statement
Delegate VoidRuntaskdelegate (IntSeconds );

// Execute task
Void Runtask ( Int Seconds)
{
// Display progress every 1/4 seconds
For ( Int I =   0 ; I < Seconds *   4 ; I ++ )
{
Thread. Sleep ( 250 );

//Display progress bar
Showprogress (seconds* 4, I+ 1);
}
}

At this point, we have used several examples to illustrate how to execute a task, how to display the task progress asynchronously through multithreading, and solve the security issues of multithreading. I hope that I can help you understand multi-threaded programming, delegate usage, asynchronous calling, and further communicate with you.


Sample package:

--- Secure multi-thread sample package

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.