The majority of modern software applications make use of several execution threads. For example, in the text editor, one thread is responsible for the spell cheking, another for autosaving, one more thread for handling the user input. The mechanism of multiple threads provides the software developer with a convenient way of structuring the functional possibilities: the software application architecture will be more stable, if it's various possibilities are programmed separately from each other. The ability to use multiple threads will be useful even for a specialist of numerical computing. The iteration methods usually need to execute a large amount of computations in order to receive an approximate solution of a certain problem. This circumstance should be taken into account at the stage of software design architecture so, that a user could follow the computational process and not worry about the responsiveness of the application. In order to launch a separate execution thread, the .Net framework provides a developer with an eective template of task-based asynchronous programming [3] that uses some new keywords async, await and classes Task, Task<TResult> from the namespace System.Threading.Tasks. The instances of this class are created very fast, they need only a little amount of system resources and they eectively use the processors time. That's why it is convenient to move the computations to a separate thread, which on its turn can also launch dierent parallel computational threads. This approach signicantly accelerates a software performance on a multiprocessor (or multi-core) computer. The keyword async in the name of an asynchronous method changes the way of how the result of this method is handled, and gives a possibility to use the instruction await for launching any awaitable object. For this purpose, in the .Net framework there are usually used the instances of the classes Task and Task<Result>. The task, launched with the instruction await, does not block the user interface thread during the computation. Before launching an synchronous task, there are dierent preparation steps: create a stop-marker CancellationToken token, an object Progress<T> progress in order to be able to send the data to the main thread, and nally a set of local variables to correctly catch the execution context. Then the asynchronous method in the right moment calls progress.Report(data), for a "soft" termination of an asynchronous algorithm. In a convenient point in time, this algorithm should check the property token.IsCancellationRequested and terminate the execution on request. The cancellation request can be initiated from the main thread by calling the method token.Cancel(). In order to synchronize the nishing of the array of asynchronous tasks, the static method Task.WhenAll(tasks).Wait() is used. For the demonstration of the described approaches an application has been created. It demonstrates how to apply the genetic algorithm in order to solve the traveling sales-man problem [6] for a large number of cities. It is experimentally analyzed how the number of threads inuences the performance of the application. The complete code base can be downloaded from the repository [4].
Read full abstract