gpt4 book ai didi

c# - 如何为 Control.BeginInvoke 委托(delegate) AsyncCallback 方法? (。网)

转载 作者:太空狗 更新时间:2023-10-29 23:11:43 25 4
gpt4 key购买 nike

是否可以以“即发即弃”方式以外的方式使用 Control.BeginInvoke?我想更改以下请求以委托(delegate)回调方法,以便我可以在每个异步调用完成时执行某些操作。

this.BeginInvoke(new RefreshRulesDelegate(RefreshRules), new object[] { ctrl, ctrl.DsRules, ctrl.CptyId });  

我可以使用普通的 delegate.BeginInvoke 来做到这一点,例如

RefreshRulesDelegate del = new RefreshRulesDelegate(RefreshRules);
del.BeginInvoke(ctrl, ctrl.DsRules, ctrl.CptyId, new AsyncCallback(RefreshCompleted), del);

但因为我正在调用 Control.BeginInvoke,所以我无法执行此操作,因为我收到“跨线程操作无效”错误。
有人帮忙吗?

根据收到的一些答案,我将澄清“原因”。我需要在我的 GUI 上加载/刷新控件而不锁定应用程序的其余部分。该控件包含许多控件 (ruleListCtls),它们都需要检索数据集并将其传递给它们。即

public void RefreshAll()
{
foreach (LTRFundingRuleListControl ctrl in ruleListCtls)
{
this.BeginInvoke(new RefreshRulesDelegate(RefreshRules), new object[]{ctrl,ctrl.DsRules, ctrl.CptyId });
}
}

我发现如果我提供一个委托(delegate)回调方法并将任何修改控件的代码移回创建它们的主 GUI 线程(以避免跨线程错误),我就可以做到这一点

public void RefreshAll()
{
IntPtr handle;
foreach (LTRFundingRuleListControl ctrl in ruleListCtls)
{
handle = ctrl.Handle;
RefreshRulesDsDelegate del = new RefreshRulesDsDelegate(RefreshRulesDs);
del.BeginInvoke(ctrl.DsRules, ctrl.CptyId, handle, out handle, new AsyncCallback(RefreshCompleted), del);
}
}

private void RefreshCompleted(IAsyncResult result)
{
CptyCatRuleDataSet dsRules;
string cptyId;
IntPtr handle;

AsyncResult res = (AsyncResult) result;

// Get the handle of the control to update, and the dataset to update it with
RefreshRulesDsDelegate del = (RefreshRulesDsDelegate) res.AsyncDelegate;
dsRules = del.EndInvoke(out handle,res);

// Update the control on the thread it was created on
this.BeginInvoke(new UpdateControlDatasetDelegate(UpdateControlDataset), new object[] {dsRules, handle});
}

public delegate CptyCatRuleDataSet RefreshRulesDsDelegate(CptyCatRuleDataSet dsRules, string cptyId, IntPtr ctrlId, out IntPtr handle);
private CptyCatRuleDataSet RefreshRulesDs(CptyCatRuleDataSet dsRules, string ruleCptyId, IntPtr ctrlId, out IntPtr handle)
{
try
{
handle = ctrlId;
int catId = ((CptyCatRuleDataSet.PSLTR_RULE_CAT_CPTY_SelRow)dsRules.PSLTR_RULE_CAT_CPTY_Sel.Rows[0]).RULE_CAT_ID;
return ltrCptyRulesService.GetCptyRules(ruleCptyId, catId);
}
catch (Exception ex)
{
throw ex;
}
}

这是我们委托(delegate)给接收到回调的主线程的内容:

private delegate void UpdateControlDatasetDelegate(CptyCatRuleDataSet dsRules, IntPtr ctrlId);
private void UpdateControlDataset(CptyCatRuleDataSet dsRules, IntPtr ctrlId)
{
IEnumerator en = ruleListCtls.GetEnumerator();
while (en.MoveNext())
{
LTRFundingRuleListControl ctrl = en.Current as LTRFundingRuleListControl;
if (ctrl.Handle == ctrlId)
{
ctrl.DsRules = dsRules;
}
}
}

这现在工作正常。然而,除了我认为这不是特别优雅之外,主要问题是异常处理。也许这是另一个问题,但如果 R​​efreshRulesDs 抛出异常,那么我的应用程序会崩溃,因为错误没有冒泡备份到 GUI 线程(显然),而是作为未处理的异常。在我能捕捉到这些之前,我将不得不同步完成整个操作。如何成功捕获错误并加载其余控件?或者我如何通过适当的异常处理以另一种方式实现此异步操作?

最佳答案

关于“是否可能”部分:不,Control.BeginInvoke 使用 Windows 的 PostMessage(),这意味着没有答案。这也意味着 RefreshRulesDelegate 在主线程上执行,而不是在后台线程上执行。

因此,使用 delegate.BeginInvoke 或 ThreadPool,当它们完成时使用 Control.[Begin]Invoke() 更新 UI。

关于c# - 如何为 Control.BeginInvoke 委托(delegate) AsyncCallback 方法? (。网),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1808636/

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