ArgumentException, TargetParameterCountException для Control.BeginInvoke(). Зачем?
Я получаю ArgumentException и TargetParameterCountException при использовании BeginInvoke ().
1) При первом вызове выдается System.ArgumentException: объект типа 'System.String' не может быть преобразован в тип 'System.Object []'.
2) Во втором вызове он дает Gives TargetParameterCountException: {"Несоответствие количества параметров."}
Почему это происходит?
using System;
using System.Threading;
using System.Windows.Forms;
namespace BeginInvokeArgsTest
{
public partial class Form1 : Form
{
private delegate void VoidDelegate(params object[] args);
private Delegate methodDelegate;
public Form1()
{
InitializeComponent();
methodDelegate = new VoidDelegate(SetLabelDelegate);
Thread t = new Thread(ChangeDay);
t.Start();
}
private void ChangeDay()
{
//Gives ArgumentException. 'System.String' cannot be converted to type 'System.Object[]'.
ChangeDay(new VoidDelegate(SetLabelDelegate), "Sunday" );
//Gives TargetParameterCountException: {"Parameter count mismatch."}
ChangeDay(new VoidDelegate(SetLabelDelegate), "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday");
}
private void ChangeDay(Delegate del, params object[] args)
{
if (this.InvokeRequired)
{
methodDelegate = del;
this.BeginInvoke(new VoidDelegate(RouterDelegate), args );
}
}
private void RouterDelegate(params object[] args)
{
methodDelegate.DynamicInvoke(args);
}
private void SetLabelDelegate(params object[] args)
{
foreach (object day in args)
{
label1.Text = day as string;
Thread.Sleep(1000);
}
}
}
}
PS: Исправил неправильно сформулированный вопрос сейчас. Мои искренние извинения за старый неправильно сформулированный вопрос. Я обычно не так небрежен. Пожалуйста, также игнорируйте ошибки синтаксиса языка, если таковые имеются.
1 ответ
Хорошо... с более полным примером, довольно легко увидеть, что происходит.
Проблема в том, что делегат ожидает один параметр, который должен быть массивом объектов.
Теперь посмотрим, как вы его вызываете:
private void ChangeDay(Delegate del, params object[] args)
{
if (this.InvokeRequired)
{
methodDelegate = del;
this.BeginInvoke(new VoidDelegate(RouterDelegate), args);
}
}
args
здесь ожидается массив аргументов... их несколько. Так что, если ваш делегат принял два строковых параметра, у вас будет object[]
длиной два, каждый элемент которого будет ссылаться на строку.
Так что вы хотите, это object[]
длиной 1, единственным элементом которого является ссылка на другой object[]
, Вы можете сделать это легко:
this.BeginInvoke(new VoidDelegate(RouterDelegate), new object[] { args });
и то же самое в RouterDelegate
:
methodDelegate.DynamicInvoke(new object[] { args });
На этом этапе я считаю, что все будет работать нормально (с точки зрения вызова делегата - вы не должны спать в потоке пользовательского интерфейса, но это другой вопрос).