gpt4 book ai didi

c# - 如何正确取消订阅事件

转载 作者:太空宇宙 更新时间:2023-11-03 23:09:31 24 4
gpt4 key购买 nike

我如何才能正确地取消订阅事件并确保现在不调用被调用的方法?

我的问题是这种代码:

public class MyClassWithEvent
{
public event EventHandler MyEvent;
public int Field;
}

public class MyMainClass
{
private MyClassWithEvent myClass;

public void Start()
{
myClass.MyEvent += new EventHandler(doSomething);
}

public void Stop()
{
myClass.MyEvent -= new EventHandler(doSomething);
myClass = null;
}

private void doSomething()
{
myClass.Field = 42;
}
}

如果在执行 doSomething 时调用 myClass = null,指令 myClass.Field = 42 会引发错误,因为 myClass 为 null。

如何确定 doSomething 在设置 myClass = null 之前没有执行?

编辑:

其他例子:

public void Stop()
{
myClass.MyEvent -= new EventHandler(doSomething);

// Can I add a function here to be sure that doSomething is not running ?

myClass.Field = 101;
}

在那种情况下,我不确定 myClass.Field 是 42 还是 101。

编辑2:

显然我的问题并不像我想的那么简单。我将解释我的确切案例。

我的代码是:

public class MyMainClass
{
object camera;//can be type uEye.Camera or DirectShowCamera
bool isRunning = false;

public void Start()
{
if (camera is uEye.Camera)
{
camera.EventFrame += new EventHandler(NewFrameArrived);
}
else if (camera is DirectShowCamera)
{
//other init
}
isRunning = true;
}

public void Stop()
{
if (camera is uEye.Camera)
{
camera.EventFrame -= new EventHandler(NewFrameArrived);
camera.exit;
}
else if (camera is DirectShowCamera)
{
//other stop
}
isRunning = false;
}

public void ChangeCamera(object new camera)
{
if (isRunning)
Stop()
camera = new camera();
}

void NewFrameArrived(object sender, EventArgs e)
{
uEye.Camera Camera = sender as uEye.Camera;
Int32 s32MemID;
Camera.Memory.GetActive(out s32MemID);

lock (_frameCameralocker)
{
if (_frameCamera != null)
_frameCamera.Dispose();
_frameCamera = null;
Camera.Memory.ToBitmap(s32MemID, out _frameCamera);
}

Dispatcher.Invoke(new Action(() =>
{
lock (_frameCameralocker)
{
var bitmapData = _frameCamera.LockBits(
new System.Drawing.Rectangle(0, 0, _frameCamera.Width, _frameCamera.Height),
System.Drawing.Imaging.ImageLockMode.ReadOnly, _frameCamera.PixelFormat);

if (_frameCamera.PixelFormat == System.Drawing.Imaging.PixelFormat.Format8bppIndexed)
{
DeviceSource = System.Windows.Media.Imaging.BitmapSource.Create(
bitmapData.Width, bitmapData.Height, 96, 96, System.Windows.Media.PixelFormats.Gray8, null,
bitmapData.Scan0, bitmapData.Stride * bitmapData.Height, bitmapData.Stride);
}

_frameCamera.UnlockBits(bitmapData);

if (OnNewBitmapReady != null)
OnNewBitmapReady(this, null);
}
}));
}
}

当我将相机从 uEye 更改为 directshow 时,我在 DeviceSource = System.Windows.Media.Imaging.BitmapSource.Create(方法 NewFrameArrived)中遇到 AccessViolationException因为我尝试从退出的相机创建 BitmapSource

最佳答案

根据您更新的问题,您唯一需要做的就是将 Stop() 操作锁定为与 Dispatcher.Invoke

相同的锁
public void Stop()
{
lock(_frameCameralocker)
{
if (camera is uEye.Camera)
{
camera.EventFrame -= new EventHandler(NewFrameArrived);
camera.exit;
}
else if (camera is DirectShowCamera)
{
//other stop
}
isRunning = false;
}
}

这将确保所有 NewFrameArrived 调用在您创建新相机之前完成或尚未开始。然后在调度程序内部检查您是否正在运行,以防帧在 Stop() 调用开始和完成之前排队。

    Dispatcher.Invoke(new Action(() =>
{
lock (_frameCameralocker)
{
if(!isRunning)
return;

var bitmapData = _frameCamera.LockBits(
new System.Drawing.Rectangle(0, 0, _frameCamera.Width, _frameCamera.Height),
System.Drawing.Imaging.ImageLockMode.ReadOnly, _frameCamera.PixelFormat);

if (_frameCamera.PixelFormat == System.Drawing.Imaging.PixelFormat.Format8bppIndexed)
{
DeviceSource = System.Windows.Media.Imaging.BitmapSource.Create(
bitmapData.Width, bitmapData.Height, 96, 96, System.Windows.Media.PixelFormats.Gray8, null,
bitmapData.Scan0, bitmapData.Stride * bitmapData.Height, bitmapData.Stride);
}

_frameCamera.UnlockBits(bitmapData);

if (OnNewBitmapReady != null)
OnNewBitmapReady(this, null);
}
}));

关于c# - 如何正确取消订阅事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39852454/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com