📄 readme.htm
字号:
<h1>Background Tasks in GUI Projects</h1>
<h2>Abstract</h2>
<p>This paper considers a way to implement background jobs in Vip6 GUI
applications using multi threading. The threads for the background jobs can be
structured in many different ways, for example starting a thread per job or
queuing the jobs for execution by a thread pool. No matter which strategy is
used there are some synchronization problems that must be solved. The solution
of these can be reused for any queue structure.</p>
<p>This paper only considers synchronization between the GUI thread and the
background jobs. Synchronized access to shared data is only covered at the
problem level (i.e. no solutions).</p>
<h2>Why use multi-threading</h2>
<p>A GUI program is event driven. It is possible to use the events to implement
background processing. The reason that multi-threading is appealing is that each
thread can by large be programmed sequentially. Without multithreading the
programmer is responsible for switching between jobs, and this means that all
the code becomes more complex (very often rather complex).</p>
<h2>Multi-threading in Windows GUI applications</h2>
<p>In MS Windows each window is owned by a thread. This thread runs the message
loop to which the window belongs. MS Windows GUI is single threaded in the sense
that only the owner thread of a window should interact directly with a window.
The only safe action a thread can perform on a window that it does not own is to
post messages to it.</p>
<h2>Multi-threading in Vip6 GUI applications</h2>
<p>Vip6 GUI programs are currently based on VPI. VPI only run one GUI thread,
which is the thread that calls <i>vpi::init</i> (At most one thread in a process
may call <i>vpi::init</i>). This thread is the one that runs the single message
loop in a VPI program. Subsequently this thread will own <i><b>all</b></i>
windows and all other threads can therefore at most post messages to windows.</p>
<h2>Shared Data</h2>
<p>Typically a lot of this data will have to be shared among threads as it
represents a "global" or shared state.</p>
<p>Threads will have to synchronize access to shared data. Otherwise some
threads might read data that is inconsistent, because other threads are updating
the data simultaneously with the reader. And likewise the data might end up
being inconsistent if several threads update the data simultaneously.</p>
<h2>Thread Communication and Synchronization</h2>
<p>There is only one thread that can interact directly with the windows, and
window handling must stay alert while background jobs run. Therefore background
jobs will have to run in non-GUI threads. At the same time both the GUI thread
and the background threads will have to manipulate the data in the application.
</p>
<p>All in all the GUI thread will have to communicate and initiate the
background jobs in the background threads. The background threads will have to
communicate the results back to the GUI thread so that they can be reflected in
the windows. Finally, all threads will have to synchronize their access to the
shared data in the application.</p>
<p>This paper only considers the GUI thread synchronization.</p>
<h2>Background jobs</h2>
<p>A background job has three main ingredients:</p>
<ul>
<li>The code to execute plus the input to the code</li>
<li>Utilization of the result in the windows of the application</li>
<li>Access to the global/shared state of the application (which will not be
considered in this paper) </li>
</ul>
<p>Consider the following piece of code:</p>
<pre>clauses
ppp(X) :-
long(X, Y),
update(Y).</pre>
<p><i>long</i> is a long operation that we want to perform as a background job,
<i>update</i> is the code that utilizes the result of <i>long</i> in the windows
of the application. In this example update is synchronous, in the sense that all
updating is done after the background part of the job is finished. We shall
return to asynchronous update of the windows below.</p>
<p>We encapsulate the job in an object, and represent each part of the job as a
<i>runnable</i> (a predicate without arguments). I.e. the background part is
represented as one runnable and the utilization of the result is represented by
another runnable.</p>
<pre>implement myJob
facts
x :
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -