Presentation is loading. Please wait.

Presentation is loading. Please wait.

Windows Development Dynadata Copyright, 2014 © DynaData S.A. 1/49.

Similar presentations


Presentation on theme: "Windows Development Dynadata Copyright, 2014 © DynaData S.A. 1/49."— Presentation transcript:

1 Windows Development Dynadata Copyright, 2014 © DynaData S.A. 1/49

2 Dynadata Multi-Threading with MFC Library
Copyright, 2014 © DynaData S.A. 2/49

3 Multi-thread Overview
Processes and Threads Worker threads User interface threads Threads & priorities Thread synchronization Costs of Creating Threads Dynadata Copyright, 2014 © DynaData S.A. 3/49

4 Processes and Threads I
A Win32®-based application consists of one or more processes. A process, in the simplest terms, is an executing program. A process is a collection of virtual memory space, code, data, and system resources, while a thread is code that is to be serially executed within a process. Dynadata Copyright, 2014 © DynaData S.A. 4/49

5 Processes and Threads II
One or more threads run in the context of the process. A thread is the basic unit to which the operating system allocates processor time. A processor executes threads, not processes, so each 32-bit application has at least one process and one thread Dynadata Copyright, 2014 © DynaData S.A. 5/49

6 Processes and Threads III
A thread can execute any part of the process code, including parts currently being executed by another thread. Prior to the introduction of multiple threads of execution, applications were all designed to run on a single thread of execution. Dynadata Copyright, 2014 © DynaData S.A. 6/49

7 Fibers I A fiber is a unit of execution that must be manually scheduled by the application. Fibers run in the context of the threads that schedule them. Each thread can schedule multiple fibers. From a system standpoint, a fiber assumes the identity of the thread that created it. Dynadata Copyright, 2014 © DynaData S.A. 7/49

8 Fibers II The only state information maintained for a fiber is its stack, a subset of its registers, and the fiber data provided during fiber creation. Fibers are not preemptively scheduled. A fiber is scheduled by switching to it from another fiber. The system still schedules threads to run. When a thread running fibers is preempted, its currently running fiber is preempted. The fiber runs when its thread runs. Dynadata Copyright, 2014 © DynaData S.A. 8/49

9 Job Objects A job object allows groups of processes to be managed as a unit. Job objects are namable, securable, sharable objects that control attributes of the processes associated with them. Operations performed on the job object affect all processes associated with the job object. Dynadata Copyright, 2014 © DynaData S.A. 9/49

10 Preemptive and Nonpreemptive Multitasking I
In a nonpreemptive multitasking scheme, the amount of time a task is allowed to run is determined by the task, whereas in a preemptive scheme, the time is determined by the operating system. Dynadata Copyright, 2014 © DynaData S.A. 10/49

11 Preemptive and Nonpreemptive Multitasking II
One important difference between the way Windows NT and Windows 3.1 multitask is that under Windows 3.1 the smallest schedulable unit is an application instance (also known as a task), whereas under Windows NT the smallest schedulable unit is a threads within the same process. Dynadata Copyright, 2014 © DynaData S.A. 11/49

12 Threads I Multiple threads in the same application have access to the same address space and thus can share memory. This is both a blessing and a curse: a blessing because that makes it fairly straightforward for multiple threads to share data and communicate with each other; a curse because the task of synchronizing access to the data can be extremely difficult. Dynadata Copyright, 2014 © DynaData S.A. 12/49

13 Dynadata Threads II MFC distinguishes two types of threads:
worker threads, for background tasks like spreadsheet recalculation User-interface (UI) threads, for gathering input and displaying output. Dynadata Copyright, 2014 © DynaData S.A. 13/49

14 Dynadata Worker threads
A worker thread is commonly used to handle background tasks that the user shouldn’t have to wait for to continue using your application. Two steps are required to get your thread running: Implementing the controlling function Starting the thread. It is not necessary to derive a class from CWinThread. Dynadata Copyright, 2014 © DynaData S.A. 14/49

15 Starting the a Worker thread
There are two overloaded versions of AfxBeginThread(): one for user-interface threads and one for worker threads. CWinThread* AfxBeginThread( AFX_THREADPROC pfnThreadProc, LPVOID pParam, int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL ); Dynadata Copyright, 2014 © DynaData S.A. 15/49

16 Starting the a Worker thread II
To begin execution of your worker thread, call AfxBeginThread() providing the following information: The address of the controlling function. The parameter to be passed to the controlling function. (Optional) The desired priority of the thread. The default is normal priority. (Optional) The desired stack size for the thread. The default is the same size stack as the creating thread. (Optional) CREATE_SUSPENDED if you want the thread to be created in a suspended state. The default is 0, or start the thread normally. (Optional) The desired security attributes. The default is the same access as the parent thread. Dynadata Copyright, 2014 © DynaData S.A. 16/49

17 Starting the a Worker thread III
AfxBeginThread creates a new CWinThread object, calls its CreateThread() function to start executing the thread, and returns a pointer to the thread. Dynadata Copyright, 2014 © DynaData S.A. 17/49

18 Implementing the Thread Controlling Function
The controlling function defines the thread. When this function is entered, the thread starts, and when it exits, the thread terminates. This controlling function should have the following prototype: UINT MyControllingFunction( LPVOID pParam ); The parameter is a single 32-bit value. The value the function receives in this parameter is the value that was passed to the constructor when the thread object was created. Dynadata Copyright, 2014 © DynaData S.A. 18/49

19 Dynadata Thread Return
When the function terminates, it should return a UINT value indicating the reason for termination. Typically, this exit code is 0 to indicate success with other values indicating different types of errors. This is purely implementation dependent. Some threads may maintain usage counts of objects, and return the current number of uses of that object. Dynadata Copyright, 2014 © DynaData S.A. 19/49

20 User interface threads
A user-interface thread is commonly used to handle user input and respond to user events independently of threads executing other portions of the application. The main application thread is the CWinApp-derived class. The first thing to do when creating a user-interface thread is derive a class from CWinThread. That class must be declared and implemented, using the DECLARE_DYNCREATE and IMPLEMENT_DYNCREATE macros. This class must override some functions, and can override others. Dynadata Copyright, 2014 © DynaData S.A. 20/49

21 Functions to Override When Creating a User-Interface Thread
Dynadata Copyright, 2014 © DynaData S.A. 21/49

22 Starting the a User-Interface thread
To start your user-interface thread, call AfxBeginThread, providing the following information: CWinThread* AfxBeginThread( CRuntimeClass* pThreadClass, int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL ); Dynadata Copyright, 2014 © DynaData S.A. 22/49

23 Starting the a User-Interface thread II
To begin execution of your user-interface thread, call AfxBeginThread() providing the following information: The RUNTIME_CLASS of the class you derived from CWinThread. (Optional) The desired priority level. The default is normal priority. (Optional) The desired stack size for the thread. The default is the same size stack as the creating thread. Dynadata Copyright, 2014 © DynaData S.A. 23/49

24 Starting the a User-Interface thread III
To begin execution of your user-interface thread, call AfxBeginThread() providing the following information: (Optional) CREATE_SUSPENDED if you want the thread to be created in a suspended state. The default is 0, or start the thread normally. (Optional) The desired security attributes. The default is the same access as the parent thread. AfxBeginThread creates a new object of that class, initializes it with the information supplied, and calls CWinThread:: CWinThread to start executing the thread. Dynadata Copyright, 2014 © DynaData S.A. 24/49

25 Dynadata Threads & priorities
Each thread is assigned a scheduling priority. The priority levels range from zero (lowest priority) to 31 (highest priority). Only the zero-page thread can have a priority of zero. The zero-page thread is a system thread. The priority of each thread is determined by the following criteria: The priority class of its process The priority level of the thread within the priority class of its process The priority class and priority level are combined to form the base priority of a thread. Dynadata Copyright, 2014 © DynaData S.A. 25/49

26 Dynadata Priority Classes
Each process belongs to one of the following priority classes: IDLE_PRIORITY_CLASS BELOW_NORMAL_PRIORITY_CLASS NORMAL_PRIORITY_CLASS ABOVE_NORMAL_PRIORITY_CLASS HIGH_PRIORITY_CLASS REALTIME_PRIORITY_CLASS By default, the priority class of a process is NORMAL_PRIORITY_CLASS. Dynadata Copyright, 2014 © DynaData S.A. 26/49

27 Dynadata Priority Levels
The following are priority levels within each priority class : THREAD_PRIORITY_IDLE THREAD_PRIORITY_LOWEST THREAD_PRIORITY_BELOW_NORMAL THREAD_PRIORITY_NORMAL THREAD_PRIORITY_ABOVE_NORMAL THREAD_PRIORITY_HIGHEST THREAD_PRIORITY_TIME_CRITICAL All threads are created using THREAD_PRIORITY_NORMAL. This means that the thread priority is the same as the process priority class. Dynadata Copyright, 2014 © DynaData S.A. 27/49

28 Dynadata Base Priority
The priority level of a thread is determined by both the priority class of its process and its priority level. The priority class and priority level are combined to form the base priority of each thread. Dynadata Copyright, 2014 © DynaData S.A. 28/49

29 Thread synchronization
To work with threads, you must be able to coordinate their actions. There are four objets to synchronize threads: Events Mutexes Semaphores Critical Sections Dynadata Copyright, 2014 © DynaData S.A. 29/49

30 Events I An event object is a synchronization object whose state can be explicitly set to signaled by use of the SetEvent() or PulseEvent() function. There are the two types of event objects, the first one is : Manual-reset An event object whose state remains signaled until it is explicitly reset to nonsignaled by the ResetEvent() function. While it is signaled, any number of waiting threads, or threads that subsequently specify the same event object in one of the wait functions, can be released. Dynadata Copyright, 2014 © DynaData S.A. 30/49

31 Events II An event object is a synchronization object whose state can be explicitly set to signaled by use of the SetEvent() or PulseEvent() function. There are the two types of event objects, the second is : Auto-reset An event object whose state remains signaled until a single waiting thread is released, at which time the system automatically sets the state to nonsignaled. If no threads are waiting, the event object's state remains signaled. Dynadata Copyright, 2014 © DynaData S.A. 31/49

32 Set Events I When the signal is on, all threads that wait for the event will receive it. When the signal is off, all threads that wait for the event become blocked. In its simplest form—a manual reset event—the event object turns its signal on and off in response to the two commands SetEvent() (signal on) and ResetEvent() (signal off). Dynadata Copyright, 2014 © DynaData S.A. 32/49

33 Set Events II An automatic reset event returns to its unsignaled state immediately after a SetEvent() command. An automatic reset event always releases only a single thread on each signal before resetting. The other workers continue to wait in line for more assignments. Dynadata Copyright, 2014 © DynaData S.A. 33/49

34 Pulse Events A pulse PulseEvent() turns the signal on for a very short time and then turns it back off. Pulsing a manual event allows all waiting threads to pass and then resets the event. Pulsing an automatic event lets one waiting thread pass and then resets the event. If no threads are waiting, none will pass. Setting an automatic event, on the other hand, causes the event to leave its signal on until some thread waits for it. As soon as one thread passes, the event resets itself. Dynadata Copyright, 2014 © DynaData S.A. 34/49

35 Dynadata Events and Processes
Unlike mutexes and semaphores, manual reset events change their state only when some thread explicitly sets or resets them. Threads in other processes can open a handle to an existing event object by specifying its name in a call to the OpenEvent() function. Dynadata Copyright, 2014 © DynaData S.A. 35/49

36 Mutexes A mutex object is a synchronization object whose state is set to signaled when it is not owned by any thread, and nonsignaled when it is owned. Only one thread at a time can own a mutex object, whose name comes from the fact that it is useful in coordinating mutually exclusive access to a shared resource. Dynadata Copyright, 2014 © DynaData S.A. 36/49

37 Dynadata Mutexes and Processes
Threads in other processes can open a handle to an existing mutex object by specifying its name in a call to the OpenMutex() function. Dynadata Copyright, 2014 © DynaData S.A. 37/49

38 Semaphores A semaphore object is a synchronization object that maintains a count between zero and a specified maximum value. The count is decremented each time a thread completes a wait for the semaphore object and incremented each time a thread releases the semaphore. When the count reaches zero, no more threads can successfully wait for the semaphore object state to become signaled. The state of a semaphore is set to signaled when its count is greater than zero, and nonsignaled when its count is zero. Dynadata Copyright, 2014 © DynaData S.A. 38/49

39 Dynadata Semaphores II
The semaphore object is useful in controlling a shared resource that can support a limited number of users. It acts as a gate that limits the number of threads sharing the resource to a specified maximum number. For example, an application might place a limit on the number of windows that it creates. It uses a semaphore with a maximum count equal to the window limit, decrementing the count whenever a window is created and incrementing it whenever a window is closed. Dynadata Copyright, 2014 © DynaData S.A. 39/49

40 Dynadata Semaphores III
A thread that owns a mutex object can wait repeatedly for the same mutex object to become signaled without its execution becoming blocked. A thread that waits repeatedly for the same semaphore object, however, decrements the semaphore's count each time a wait operation is completed; the thread is blocked when the count gets to zero. Similarly, only the thread that owns a mutex can successfully call the ReleaseMutex() function, though any thread can use ReleaseSemaphore() to increase the count of a semaphore object. Dynadata Copyright, 2014 © DynaData S.A. 40/49

41 Semaphores and Processes
Threads in other processes can open a handle to an existing semaphore object by specifying its name in a call to the OpenSemaphore() function. Dynadata Copyright, 2014 © DynaData S.A. 41/49

42 Dynadata Critical Sections I
Critical section objects provide a faster, and efficient mechanism for mutual-exclusion of code execution. Dynadata Copyright, 2014 © DynaData S.A. 42/49

43 Dynadata Critical Sections II
Like a mutex object, a critical section object can be owned by only one thread at a time, which makes it useful for protecting a shared resource from simultaneous access. There is no guarantee about the order in which threads will obtain ownership of the critical section, however, the system will be fair to all threads. Dynadata Copyright, 2014 © DynaData S.A. 43/49

44 Dynadata Critical Sections III
A thread uses the EnterCriticalSection() or TryEnterCriticalSection() function to request ownership of a critical section. It uses the LeaveCriticalSection() function to release ownership of a critical section. If the critical section object is currently owned by another thread, EnterCriticalSection() waits indefinitely for ownership Dynadata Copyright, 2014 © DynaData S.A. 44/49

45 Dynadata Critical Sections IV
Once a thread owns a critical section, it can make additional calls to EnterCriticalSection() or TryEnterCriticalSection() without blocking its execution. Dynadata Copyright, 2014 © DynaData S.A. 45/49

46 Critical Sections and Processes
Critical Section objects can be used only by the threads of a single process. Dynadata Copyright, 2014 © DynaData S.A. 46/49

47 Costs of Creating Threads I
The following list enumerates some of the costs incurred when creating multiple threads in your process. Memory is needed for the structures required by threads. An application that has a large number of threads consumes extra CPU time in keeping track of those threads. Dynadata Copyright, 2014 © DynaData S.A. 47/49

48 Costs of Creating Threads II
The following list enumerates some of the costs incurred when creating multiple threads in your process. An application is responsible for synchronizing access to shared resources by multiple threads. This is true for system resources (such as communications ports or disk drives), handles to resources shared by multiple processes (such as file or pipe handles), or the resources of a single process (such as global variables accessed by multiple threads). If you don't synchronize multiple threads properly (in the same or in different processes), you can run into some nasty problems, including the dreaded deadlock and race conditions. Dynadata Copyright, 2014 © DynaData S.A. 48/49

49 Costs of Creating Threads III
Because all threads of a process share the same address space and can access the process's global variables, an application must also synchronize access to these global variables. This means that the developer must decide what data can be process-specific and what data is thread-specific. Dynadata Copyright, 2014 © DynaData S.A. 49/49


Download ppt "Windows Development Dynadata Copyright, 2014 © DynaData S.A. 1/49."

Similar presentations


Ads by Google