Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.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
C# 如何防止重复、宏或其他内容?_C#_Delegates - Fatal编程技术网

C# 如何防止重复、宏或其他内容?

C# 如何防止重复、宏或其他内容?,c#,delegates,C#,Delegates,问题是,对于每个传递到GUI的事件,我都有很多这样的代码,如何缩短这些代码?宏无法完成我想的工作。有没有一种更通用的方法来做“模板”之类的事情 private delegate void DownloadProgressDelegate(object sender, DownloaderProgressArgs e); void DownloadProgress(object sender, DownloaderProgressArgs e) { if (this.InvokeRequi

问题是,对于每个传递到GUI的事件,我都有很多这样的代码,如何缩短这些代码?宏无法完成我想的工作。有没有一种更通用的方法来做“模板”之类的事情

private delegate void DownloadProgressDelegate(object sender, DownloaderProgressArgs e);
void DownloadProgress(object sender, DownloaderProgressArgs e) {
    if (this.InvokeRequired) {
        this.BeginInvoke(new DownloadProgressDelegate(DownloadProgress), new object[] { sender, e });
        return;
    }

    label2.Text = d.speedOutput.ToString();
}
编辑:

好的,如何在BeginInvoke中使用匿名委托进行此操作:

this.BeginInvoke(new DownloadProgressDelegate(DownloadProgress), new object[] { sender, e });

你可以试试。。。但我不知道它是否适合你的情况

一个简单的想法是创建一个例程,该例程基于请求类型枚举并使用switch语句处理所有BeginInvoke情况。那么至少您只需要检查invokererequired一次。请注意,您可能应该使用if/else而不是return来控制流。

好的,一种方法是将泛型代码放在静态类中,并像这样访问它,例如:

Utility.DownloadSpeedUpdate(frm, sender, e);

我个人更喜欢将实际操作放在
操作中,然后检查
是否需要调用——这还有一个好处,即不需要声明太多的
委托
以用于您的
BeginInvoke
s。换句话说,

void DownloadProgress(object sender, DownloaderProgressArgs e) 
{
    Action updateLabel = () => label2.Text = d.speedOutput.ToString();

    if (this.InvokeRequired) 
    {
        this.BeginInvoke(updateLabel);
    }
    else
    {
       updateLabel();
    }
}

void DownloadSpeed(object sender, DownloaderProgressArgs e) {

    Action updateSpeed = () => 
    {
        string speed = "";
        speed = (e.DownloadSpeed / 1024).ToString() + "kb/s";
        label3.Text = speed;
    };

    if (this.InvokeRequired)
    {
        this.BeginInvoke(updateSpeed);
    }
    else
    {
        updateSpeed();
    }
}
这种方法非常适合在
控件
上使用扩展方法,该方法执行
操作
,并通过检查
调用所需的
来运行它

扩展方法至少应类似于:

public static void MaybeInvoke(this Control c, Action action)
{
   if (c.InvokeRequired)
   {
       this.BeginInvoke(action);
   }
   else
   {
       action();
   }
}
令人烦恼的是,非通用的
操作直到.NET 3.5才被引入,因此您需要对我给出的示例中的内容进行一些修改——如果您使用的是早期版本,可能需要使用
MethodInvoker

.NET(从某种意义上说)有一个相当糟糕的UI框架,它会积极地鼓励您出现问题,以及业务逻辑和UI的混合

您可能能够在泛型、委托和基类/静态助手方法方面取得一些进展

然而,理想情况下,您需要在.net之上分层一个UI管理器,以帮助您正确地完成此任务。这将允许您将UI与其执行的命令分离(即,您将动态地将UI事件(如按键、菜单选项、按钮单击等)绑定到底层命令对象,而不是直接处理UI事件)。UI事件处理程序只需查找绑定到事件的命令,然后调用集中的“execute command X”方法,这将处理到UI线程的所有封送,等等

除了清理这些混乱之外,这还允许您轻松地将密钥绑定和脚本/自动化等内容添加到应用程序中,并使UI具有无限的可扩展性和可维护性


这不是巧合,这是WCF中使用的核心命令分派方法-如果您不使用WCF,那么不幸的是,由您来实现等效的命令分派方法。实现一个基本的命令分派系统需要一点工作,但除非您的应用程序很简单,否则您会很高兴这样做。

如果您有许多函数需要调用所需的检查,下面的示例将为您节省大量代码。你应该注意一些重要的事情:

  • 我使用
    EventHandler
    ,而不是为每个函数创建新委托
  • GetInvokeRequiredDelegate函数包装了所有这些函数的相同代码
  • 这段代码可以移动到一个静态类中,以便在多个表单之间共享,但这需要更多的工作和不同的结构。在这里,函数只知道处理的是哪个表单,因为函数存在于表单内部
这是我为测试GetInvokeRequiredDelegate()而设置的所有代码:

公共部分类表单1:表单
{
公共事件事件处理程序OnDownloadProgress;
公共事件处理程序OnDownloadSpeed;
公共表格1()
{
初始化组件();
OnDownloadProgress+=GetInvokeRequiredDelegate(下载进度);
OnDownloadSpeed+=GetInvokereRequiredDelegate(下载速度);
新系统.Threading.Thread(Test.Start();
}
公开无效测试()
{
OnDownloadProgress(这是新的DownloaderProgressArgs(){DownloadSpeed=1000,speedOutput=5});
OnDownloadSpeed(这是新的DownloaderProgressArgs(){DownloadSpeed=2000,speedOutput=10});
}
EventHandler GetInvokeRequiredDelegate(操作操作),其中T:EventArgs
{
返回((o,e)=>
{
if(this.invokererequired)
{
this.BeginInvoke(action,新对象[]{o,e});
}否则
{
行动(o,e);
}
});
}
void DownloadProgress(对象发送方,DownloaderProgressArgs d)
{
label2.Text=d.speedOutput.ToString();
}
void DownloadSpeed(对象发送方,DownloaderProgressArgs e)
{
字符串速度=”;
速度=(例如下载速度/1024).ToString()+“kb/s”;
标签3.文本=速度;
}
}
公共类下载程序args:EventArgs{
公共int下载速度;
公共产出;
}
    public partial class Form1 : Form
    {
        public event EventHandler<DownloaderProgressArgs> OnDownloadProgress;
        public event EventHandler<DownloaderProgressArgs> OnDownloadSpeed;

        public Form1()
        {
            InitializeComponent();

            OnDownloadProgress += GetInvokeRequiredDelegate<DownloaderProgressArgs>(DownloadProgress);
            OnDownloadSpeed += GetInvokeRequiredDelegate<DownloaderProgressArgs>(DownloadSpeed);

            new System.Threading.Thread(Test).Start();
        }

        public void Test()
        {
            OnDownloadProgress(this, new DownloaderProgressArgs() { DownloadSpeed = 1000, speedOutput = 5 });
            OnDownloadSpeed(this, new DownloaderProgressArgs() { DownloadSpeed = 2000, speedOutput = 10 });
        }

        EventHandler<T> GetInvokeRequiredDelegate<T>(Action<object, T> action) where T : EventArgs
        {
            return ((o, e) =>
            {
                if (this.InvokeRequired)
                {
                    this.BeginInvoke(action, new object[] { o, e});
                } else 
                {
                    action(o, e);
                }
            });
        }


        void DownloadProgress(object sender, DownloaderProgressArgs d)
        {
            label2.Text = d.speedOutput.ToString();
        }

        void DownloadSpeed(object sender, DownloaderProgressArgs e)
        {
            string speed = "";
            speed = (e.DownloadSpeed / 1024).ToString() + "kb/s";
            label3.Text = speed;
        }
    }

    public class DownloaderProgressArgs : EventArgs {
        public int DownloadSpeed;
        public int speedOutput;
    }