Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
线程难题-等待UI线程中的线程(C#)_C#_Wpf_Multithreading_Task_Infinite Loop - Fatal编程技术网

线程难题-等待UI线程中的线程(C#)

线程难题-等待UI线程中的线程(C#),c#,wpf,multithreading,task,infinite-loop,C#,Wpf,Multithreading,Task,Infinite Loop,我有一个奇怪的鸡和蛋的问题: 我有一个任务,从相机上拍摄图像,并将它们放在UI(WPF)上。 当我退出应用程序窗口时,我想正确关闭相机,因此我调用Dispose()。但是,如果缓冲区中仍有图像,相机将无法关闭,因此我必须等待该线程完成(通过更改“isLive”布尔值触发线程停止) 但是,线程使用UI中的调度程序发布图像。从UI线程调用线程上的“Wait()”会使其暂停UI线程,这反过来会在尝试更新UI时暂停摄影机线程,使其无限期挂起 下面是我的代码的简单版本。这有什么窍门吗 public voi

我有一个奇怪的鸡和蛋的问题:

我有一个任务,从相机上拍摄图像,并将它们放在UI(WPF)上。 当我退出应用程序窗口时,我想正确关闭相机,因此我调用Dispose()。但是,如果缓冲区中仍有图像,相机将无法关闭,因此我必须等待该线程完成(通过更改“isLive”布尔值触发线程停止)

但是,线程使用UI中的调度程序发布图像。从UI线程调用线程上的“Wait()”会使其暂停UI线程,这反过来会在尝试更新UI时暂停摄影机线程,使其无限期挂起

下面是我的代码的简单版本。这有什么窍门吗

public void GoLive()
{
    isLive = true;
    cameraTask = Task.Run(new Action(() =>
    {
        cam.BeginAcquisition();
        while (isLive)
        {
            var rawImage = cam.GetNextImage(); // gets raw img from camera buffer

            // now make image appear on my UI
            UIDispatcher.Invoke(new Action(() =>
            {
                // this happens on the UI thread 
                uiImage = ConvertRawToBitmapSource(rawImage);
            }));
        }
}

// when you click to exit the window, this Dispose() method gets called:

public void Dispose()
{
    isLive = false; // a field boolean
    cameraTask.Wait(); // <------ hangs here infinitely!!!
    cam.DeInit(); // shut down the camera
}
public void GoLive()
{
isLive=真;
cameraTask=Task.Run(新操作(()=>
{
cam.BeginAcquisition();
while(isLive)
{
var rawImage=cam.GetNextImage();//从摄影机缓冲区获取原始img
//现在让图像出现在我的UI上
UIDispatcher.Invoke(新操作(()=>
{
//这发生在UI线程上
uiImage=ConvertRawToBitmapSource(rawImage);
}));
}
}
//单击退出窗口时,将调用此Dispose()方法:
公共空间处置()
{
isLive=false;//一个布尔字段

等等;//您可以将
UIDispatcher.Invoke
更改为
UIDispatcher.BeginInvoke
以避免对UI线程的同步调用。但是,您需要确保当UI线程转换图像时,
rawImage
的所有权仍然有效。因此,必须将
rawImage
的所有权移到操作对象t以避免数据争用。

您可以简单地在UI线程中运行采集循环,并在单独的任务中获取每个帧。现在,要停止,只需设置
isLive=false:

public async Task RunAcquisition()
{
    cam.BeginAcquisition();

    while (isLive)
    {
        var rawImage = await Task.Run(() => cam.GetNextImage());

        uiImage = ConvertRawToBitmapSource(rawImage);
    }

    cam.DeInit();
}
相机甚至可能有一个等待的
GetNextImageAsync
方法,这将进一步简化循环:

public async Task RunAcquisition()
{
    cam.BeginAcquisition();

    while (isLive)
    {
        var rawImage = await cam.GetNextImageAsync();

        uiImage = ConvertRawToBitmapSource(rawImage);
    }

    cam.DeInit();
}

好的,你如何改变“isLive”flag..否则它会不断尝试获取下一个映像您是否意识到,使用这样的bool发送信号只会在具有强内存模型的CPU上正常工作?该代码不会在具有弱内存模型(如ARM7)的CPU上工作,除非您将bool标记为易失性并且仍然不可靠。当然,您不应该在
Disp中等待ose()
。不幸的是,你的问题提供的信息非常少。比如,你怎么知道你已经处理了缓冲区中的所有图像?比如,如果你要关机,你真的需要将图像传递给UI线程吗?比如,你听说过像
异步
等待
,和
任务完成源代码
这样的事情吗这里有太多的未知数,使问题过于宽泛。您需要缩小范围,包括提供一个很好的演示代码是如何工作的。我只想调用DeInit()当我退出应用程序时,不是每次退出LiveMode时。我有一个按钮,只需设置isLive=false即可停止LiveMode,这很好。我最终使Dispose()函数异步,并等待一个while循环,使用函数cam.IsStreaming()检查相机是否仍在流.目前看来效果不错,不管这是不是一个好的编程实践,我都不知道。