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