如何将变量传递给任务工厂操作?

时间:2011-08-04 16:22:43

标签: c# multithreading

我喜欢使用任务发送邮件。这是我用来调用SendMail方法的代码:

Task.Factory.StartNew(() => SendMail(toTextBox.Text,
                                     subjectTextbox.Text,
                                     BodyEditor.ContentHtml,
                                     filenames.ToArray(),
                                     ccTextBox.Text,
                                     bccTextBox.Text));

问题是:我无法像这样传递UI信息(文本框等),因为对象归另一个线程所有。

错误消息:调用线程无法访问此对象,因为另一个线程拥有它。

我应该如何将这些参数传递给我的行动?

3 个答案:

答案 0 :(得分:7)

您已经的UI线程中吗?如果是这样,您只需要首先提取属性,这样当调用lambda表达式时,您已经执行了属性访问。

例如:

string recipient = toTextBox.Text;
string subject = subjectTextBox.Text;
string html = BodyEditor.ContentHtml;
string cc = ccTextBox.Text;
string bcc = bcTextBox.Text();

Task.Factory.StartNew(() => SendMail(recipient,
                                     subject,
                                     html,
                                     filenames.ToArray(),
                                     cc,
                                     bcc));

变量将由lambda表达式捕获 - 基本上编译器将为你生成一个额外的类,它会松开信息,这样当lambda表达式被评估时,它仍然可用。 / p>

如果此代码在UI线程中执行而不是,那么您需要基本上将整个事物包装在另一个操作中,以在UI线程中执行它: / p>

Action action = () {
    string recipient = toTextBox.Text;
    string subject = subjectTextBox.Text;
    string html = BodyEditor.ContentHtml;
    string cc = ccTextBox.Text;
    string bcc = bcTextBox.Text();

    Task.Factory.StartNew(() => SendMail(recipient,
                                         subject,
                                         html,
                                         filenames.ToArray(),
                                         cc,
                                         bcc));
};

// Or Dispatcher.BeginInvoke(action); for WPF/Silverlight.
BeginInvoke(action);

答案 1 :(得分:3)

声明符合UI变量值的新变量并将其传递给任务

string to = toTextBox.Text;
string subject = subjectTextBox.Text;
string cc = ccTextBox.Text;
string bcc = bccTextBox.Text;
string files = filenames.ToArray();

Task.Factory.StartNew(() => SendMail(to, subject,BodyEditor.ContentHtml, files, cc, bcc));

答案 2 :(得分:1)

如果您没有直接使用对象及其属性,而是将您希望使用的值复制到变量中,然后将它们传递给它们,它会不会起作用?