如何让事件自行注销

How to have event unregister itself

我正在使用 Grpc 取消长运行 操作。我已将其设置为当服务器接收到 'Cancel' 命令时,它会向 SyncEnd 任务注册一个任务,以便在 long-运行 操作 实际上 已取消。

有没有办法让这个事件处理程序在工作完成后自行取消注册?如果没有,要么服务器因为任务已经完成而崩溃,要么我需要将事件清零作为'SyncEnd'事件的最后一个动作(我不确定这是个好主意......我真的不想每次触发事件时都必须重新注册事件)

我现在拥有的:

public override Task<CancelConfirm> CancelSync(CancelRequest request, ServerCallContext context)
{
    var tcs = new TaskCompletionSource<CancelConfirm>();
    Program.MyClass.SyncEnd += (sender, eventArgs) =>
    {
        tcs.SetResult(new CancelConfirm { Cancelled = true });
    };
    Program.MyClass.Cancel();
    return tcs.Task;
}

Button

的上下文中
btn2.Click += Btn2_Click;//to register
btn2.Click -= Btn2_Click;//to unregister

完整代码段示例。

using System.Drawing;
using System.Windows.Forms;

namespace UnregisterEvent_46936409
{

    public partial class Form1 : Form
    {
        Button btn1 = new Button();
        TextBox txtbx = new TextBox();
        public Form1()
        {
            InitializeComponent();
            btn1.Location = new Point(5,5);
            txtbx.Location = new Point(5, btn1.Location.Y + btn1.Height + 2);
            this.Controls.Add(btn1);
            this.Controls.Add(txtbx);
            btn1.Click += (sender2, context2) => DoSomethingCool("put me in there", "yahoo");//subscribe to event handler
        }

        private void DoSomethingCool(string incoming1, string incoming2)
        {
            txtbx.Text = incoming1 + incoming2;
            btn1.Click -= (Sender2, context2) => DoSomethingCool("shouldnt do anything","blah blah");//unsubscribe from the event
        }
    }
}

使用委托来实现所需的行为。

public override Task<CancelConfirm> CancelSync(CancelRequest request, ServerCallContext context) {
    var tcs = new TaskCompletionSource<CancelConfirm>();
    EventHandler handler = null;
    handler = (sender, eventArgs) =>
    {
        Program.MyClass.SyncEnd -= handler; //unregister itself
        tcs.SetResult(new CancelConfirm { Cancelled = true });
    };
    Program.MyClass.SyncEnd += handler; //
    Program.MyClass.Cancel();
    return tcs.Task;
}