Matlab “如何报告工人”;事件“;在客户端gui中

Matlab “如何报告工人”;事件“;在客户端gui中,matlab,parallel-processing,Matlab,Parallel Processing,我已经获得了的试用版,可以进行一些测试,看看它是如何工作的 在我想要执行的测试中,我想看看如何使用这个工具箱从GUI中运行一些后台处理,并报告处理进度 到目前为止,我已经创建了一个简单的GUI,它有一个在后台启动/取消处理的按钮(使用)和一个报告进程的标签 一切正常(代码在后台运行,我能够处理后台错误或取消),唯一的问题是在客户端会话中报告后台处理进度: function [] = TestBackgroundWorker() %[ % Create interface fig

我已经获得了的试用版,可以进行一些测试,看看它是如何工作的

在我想要执行的测试中,我想看看如何使用这个工具箱从GUI中运行一些后台处理,并报告处理进度

到目前为止,我已经创建了一个简单的GUI,它有一个在后台启动/取消处理的按钮(使用)和一个报告进程的标签

一切正常(代码在后台运行,我能够处理后台错误或取消),唯一的问题是在客户端会话中报告后台处理进度:

function [] = TestBackgroundWorker()
%[
    % Create interface
    fig = figure();
    cuo = onCleanup(@()delete(fig));
    stState = uicontrol('Parent', fig, 'Units', 'normalized', 'Position', [0.1 0.7 0.8 0.2], 'Style', 'text', 'String', 'Ready');
    btnOkCancel = uicontrol('Parent', fig, 'Units', 'normalized', 'Position', [0.1 0.1 0.8 0.5], 'Style', 'pushbutton', 'String', 'Go', 'Callback', @(s,e)onOkCancelClicked(fig)); 

    % Backstore
    data = guidata(fig);
    data.bgw = [];
    data.stState = stState;
    data.btnOkCancel = btnOkCancel;
    guidata(fig, data);

    waitfor(fig);   
%]
end
function [] = onBackgroundProgress(fig, ratio, msg)
%[
    % Here I would like to 'BeginInvoke' in client thread
    % to refresh 'ratio/msg' in the GUI.

    % Below code of course doesn't work:
    % 1) It is not synchronized with UI thread
    % 2) It is executed in a session with no display
    data = guidata(fig);
    set(data.stState, 'String', sprintf('%f - %s', ratio, msg));       
%]
end
function [] = onOkCancelClicked(fig)
%[
    % Backstore
    data = guidata(fig);        
    if (~isfield(data, 'bgw'))
        data.bgw = [];        
    end

    if (isempty(data.bgw))

        % Start background work
        set(data.btnOkCancel, 'String', 'Cancel');
        data.bgw = parfeval(@doBackgroundWork, 0, @(r, m)onBackgroundProgress(fig, r, m));
        guidata(fig, data);

        % Wait for error/termination/cancel
        while(true)

            try
                idx = fetchNext(data.bgw, 0.3);
            catch err

                if (~isempty(err.cause) && (strcmp(err.cause{1}.identifier, 'parallel:fevalqueue:ExecutionCancelled')))
                    % Error was due to cancelation
                    uiwait(msgbox('Processing canceled by user!', 'modal'));
                    set(data.btnOkCancel, 'String', 'Go', 'Enable', 'on');
                else
                    % Error real error (TODO: display it in some way)
                    uiwait(msgbox('Processing error!', 'modal'));
                    set(data.btnOkCancel, 'String', 'Go', 'Enable', 'on');
                end

                data.bgw = [];
                guidata(fig, data);
                break;
            end

            if (isempty(idx))
                % Still processing => Enable message pump to read GUI events
                drawnow limitrate; 
            else
                % Processing done
                uiwait(msgbox('Processing done!', 'modal'));
                data.bgw = [];
                guidata(fig, data);
                set(data.btnOkCancel, 'String', 'Go', 'Enable', 'on');
                break;
            end
        end

    else

        % Cancel background work
        set(data.btnOkCancel, 'String', 'Cancelling...', 'Enable', 'off');
        cancel(data.bgw);

    end    
%]
end
function [] = doBackgroundWork(onProgress)
%[
    count = 10;
    for k = 1:count,        
        onProgress((k-1)/count, sprintf('Step %i / %i', k, count)); 
        pause(1);       
    end
%]
end
我很理解这个问题,即回调
onBackgroundProgress
是从一个没有显示的会话执行的,因此不会发生任何事情(而且它不与客户端GUI同步)

是否有一种方法可以同步数据并将数据从工作程序传递到GUI(在C语言中,我会使用
BeginInvoke
)?可能我没有以适当的方式使用工具箱来实现我想要的(似乎更倾向于分布式计算而不是多线程),有没有其他方法来使用这个工具箱呢

编辑

我修改了我的代码以替换为对象(这是可行的),并尝试使用UI并将其与后台会话同步(这不可行):

%
%目的:
%
%测试函数,查看如何在计算时具有响应GUI
%正在后台运行。
%
%语法:
%
%[]=TestBackgroundWorker();
%
%%---主要程序
函数[]=TestBackgroundWorker()
%[
%确保并行池已启动
gcp();
%创建接口
%一个带有go/cancel按钮和标签的简单图形。
图=图();
cuo=onCleanup(@()删除(图));
stState=uicontrol('Parent',fig','Units','normalized','Position',[0.1 0.7 0.8 0.2],'Style','text','String','Ready!');
btnStartCancel=uicontrol('Parent',fig',Units','normalized','Position',[0.1 0.1 0.8 0.5],'Style','Button','String','Start','Callback',@(s,e)onOkCancelClicked(fig));
%后备箱
数据=GUI数据(图);
data.stState=stState;
data.btnStartCancel=btnStartCancel;
图形数据(图,数据);
%等待图形关闭
等待(图);
%]
结束
%%--GUI中“转到/取消”按钮的事件处理程序
函数[]=onOkCancelClicked(图)
%[
%后滩
数据=GUI数据(图);
if(~isfield(数据,'bgw'))
data.bgw=[];
结束
%取决于后台进程是否正在运行
if(isempty(data.bgw))
%开始背景工作
设置(data.btnStartCancel,'String','Cancel');
data.bgw=parfeval(@doBackgroundWork,0,@(r,m)onBackgroundProgress(图,r,m));
%启动计时器以监视bgw
data.bgwtimer=计时器('ExecutionMode','fixedSpacing','Period',0.1。。。
"TimerFcn",@(s,e)onBackgroundCheck(图,data.bgw);;
图形数据(图,数据);
启动(data.bgwtimer);
其他的
%取消背景工作
p=gcp('nocreate');%确保parpool已启动
如果(~isempty(p))
取消(data.bgw);
结束
设置(data.btnStartCancel,'String','canceling(请稍候)…..,'Enable','off');
结束
%]
结束
%%---用于监视后台工作程序的事件处理程序
功能[]=onBackgroundCheck(图,bgw)
%[    
尝试
idx=fetchNext(bgw,0.3);
如果(isempty(idx)),
%检查来自后台工作程序的消息
if((numlabs~=1)和&labProbe)
data=labReceive();
背景进展(数据{:});
结束
其他的
已完成的背景(图);
结束
犯错误
onBackgroundCompleted(图,err);
结束
%]
结束
函数[]=onBackgroundCompleted(图,错误)
%[
如果(nargin<2),err=[];结束
如果(是空的(错误))
%正常完成
uiwait(msgbox('Processing done!','Processing','help','modal');
elseif(~isempty(err.cause)&&&(strcmp(err.cause{1}.identifier,'parallel:fevalqueue:ExecutionCancelled'))
%错误是由于取消
uiwait(msgbox('Processing cancelled by user!','Processing','help','modal');
其他的
%Error real Error(TODO:以某种方式显示)
uiwait(msgbox(sprintf('Processing error:%s',err.message),'Processing','error','modal');
结束
数据=GUI数据(图);
data.bgw=[];
停止(data.bgwtimer);
set(data.stState,'String','Ready!');
设置(data.btnStartCancel、“String”、“Start”、“Enable”、“on”);
图形数据(图,数据);
%]
结束
%%---用于报告进度状态的事件处理程序
函数[]=onBackgroundProgress(图、比率、消息)
%[
cw=getCurrentWorker();
如果(~isempty(cw))
%都是后台线程,所以向GUI发送消息
%注意:正在进行广播,因为我不知道gui的id
labBroadcast(labindex,{fig,ratio,msg});
其他的
%你是GUI吗
数据=GUI数据(图);
set(data.stState,'String',sprintf('%f-%s',ratio,msg));
结束
%]
结束
%%---要在后台执行的处理
函数[]=doBackgroundWork(onProgress)
%[
计数=15;
对于k=1:count,
onProgress((k-1)/count,sprintf('Step%i/%i',k,count));
暂停(1);
结束
%]
结束

显然,
labSend
一个
labReceive
只能发生在工作人员之间,而不能发生在客户端。。。这似乎是一条死胡同。

如果你的唯一目标是监控员工的进度,你可能想退出。它还为您提供了如何建立从workers到client的套接字连接的想法,您可以使用它来构建更复杂的UI。

我不是PCT专家,但我认为这不会
%
% PURPOSE:
%
%   Test function to see how to have a responsive GUI while computations
%   are running in the background.
%
% SYNTAX:
%
%   [] = TestBackgroundWorker();
%

%% --- Main routine
function [] = TestBackgroundWorker()
%[
    % Make sure parallel pool is started
    gcp();

    % Create the interface
    % A simple figure with a go/cancel button and a label. 
    fig = figure();
    cuo = onCleanup(@()delete(fig));
    stState = uicontrol('Parent', fig, 'Units', 'normalized', 'Position', [0.1 0.7 0.8 0.2], 'Style', 'text', 'String', 'Ready!');
    btnStartCancel = uicontrol('Parent', fig, 'Units', 'normalized', 'Position', [0.1 0.1 0.8 0.5], 'Style', 'pushbutton', 'String', 'Start', 'Callback', @(s,e)onOkCancelClicked(fig)); 

    % Backstore for later use
    data = guidata(fig);    
    data.stState = stState;
    data.btnStartCancel = btnStartCancel;
    guidata(fig, data);

    % Wait until figure is closed
    waitfor(fig);   
%]
end

%% -- Event handler for 'go/cancel' button in the GUI
function [] = onOkCancelClicked(fig)
%[
    % Backstore
    data = guidata(fig);        
    if (~isfield(data, 'bgw'))
        data.bgw = [];        
    end


    % Depending if background process is running or not
    if (isempty(data.bgw))

        % Start background work
        set(data.btnStartCancel, 'String', 'Cancel');
        data.bgw = parfeval(@doBackgroundWork, 0, @(r, m)onBackgroundProgress(fig, r, m));

        % Start timer to monitor bgw
        data.bgwtimer = timer('ExecutionMode', 'fixedSpacing', 'Period', 0.1, ...
                              'TimerFcn', @(s,e)onBackgroundCheck(fig, data.bgw));

        guidata(fig, data);                          
        start(data.bgwtimer);

    else

        % Cancel background work
        p = gcp('nocreate'); % Make sure parpool is started
        if (~isempty(p))
            cancel(data.bgw);
        end
        set(data.btnStartCancel, 'String', 'Cancelling (please wait)...', 'Enable', 'off');

    end    
%]
end

%% --- Event handlers for monitoring the background worker
function [] = onBackgroundCheck(fig, bgw)
%[    
    try

        idx = fetchNext(bgw, 0.3);
        if (isempty(idx)),

            % Check for messages from the background worker
            if ((numlabs ~= 1) && labProbe)
                data = labReceive();
                onBackgroundProgress(data{:});
            end

        else    
            onBackgroundCompleted(fig);
        end

    catch err

        onBackgroundCompleted(fig, err);

    end    
%]
end
function [] = onBackgroundCompleted(fig, err)
%[
    if (nargin < 2), err = []; end

    if (isempty(err))
        % Normal completion
        uiwait(msgbox('Processing done!', 'Processing', 'help', 'modal'));
    elseif (~isempty(err.cause) && (strcmp(err.cause{1}.identifier, 'parallel:fevalqueue:ExecutionCancelled')))
        % Error was due to cancelation
        uiwait(msgbox('Processing canceled by user!', 'Processing', 'help', 'modal'));
    else
        % Error real error (TODO: display it in some way)
        uiwait(msgbox(sprintf('Processing error: %s', err.message), 'Processing', 'error', 'modal'));                    
    end 

    data = guidata(fig);
    data.bgw = [];
    stop(data.bgwtimer);
    set(data.stState, 'String', 'Ready!');
    set(data.btnStartCancel, 'String', 'Start', 'Enable', 'on');
    guidata(fig, data);        
%]
end

%% --- Event handler for reporting progression status
function [] = onBackgroundProgress(fig, ratio, msg)
%[
    cw = getCurrentWorker();

    if (~isempty(cw))
        % Were are the background thread so send message to the GUI
        % NB: Doing broadcast as I don't know the id of the gui
        labBroadcast(labindex, {fig, ratio, msg });
    else
        % Were are the GUI
        data = guidata(fig);
        set(data.stState, 'String', sprintf('%f - %s', ratio, msg));
    end    
%]
end

%% --- Processing to be performed in the background
function [] = doBackgroundWork(onProgress)
%[
    count = 15;
    for k = 1:count,        
        onProgress((k-1)/count, sprintf('Step %i / %i', k, count)); 
        pause(1);       
    end
%]
end