Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.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
.net 如何同时操作UI线程上的两个不同控件?_.net_Winforms_Multithreading - Fatal编程技术网

.net 如何同时操作UI线程上的两个不同控件?

.net 如何同时操作UI线程上的两个不同控件?,.net,winforms,multithreading,.net,Winforms,Multithreading,如何在保持应用程序的UI线程响应性的同时连续操纵标签的文本?我正在VisualStudio2010中创建一个windows窗体应用程序。另外,如果您能在vb.net或c#中发布示例,我将非常感谢 您必须从另一个线程使用BeginInvoke,这将改变UI线程上UI控件的状态。如果您使用的是.NET Framework 4,则可以使用异步任务 此代码将在新线程上启动某些内容: var myBackgroundTask = Task.Factory.StartNew(() => MyBackG

如何在保持应用程序的UI线程响应性的同时连续操纵标签的文本?我正在VisualStudio2010中创建一个windows窗体应用程序。另外,如果您能在vb.net或c#中发布示例,我将非常感谢

您必须从另一个线程使用
BeginInvoke
,这将改变UI线程上UI控件的状态。

如果您使用的是.NET Framework 4,则可以使用异步任务

此代码将在新线程上启动某些内容:

var myBackgroundTask = Task.Factory.StartNew(() => MyBackGroundMethod());
您说要更新用户界面(UI),因为UI上的控件是在主线程上创建的,直接从另一个线程访问它们将引发跨线程异常。但是,您可以从后台线程启动一个新任务,并告诉它在主线程上运行,如下所示:

private void MyMethod()
{
   var uiTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
   var myBackgroundTask = Task.Factory.StartNew(() => MyBackGroundMethod(uiTaskScheduler));
}

private void MyBackGroundMethod(TaskScheduler uiTaskScheduler)
{
    Task.Factory.StartNew(
            () => { TextBox1.Text = "Hello from separate thread"; },
            CancellationToken.None,
            TaskCreationOptions.None,
            uiTaskScheduler);
}
var finishedTask = myBackgroundTask.ContinueWith(
                    x => Label1.Text = "Task 1 completed sucessfully",
                    CancellationToken.None,
                    TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnRanToCompletion,
                    uiTaskScheduler);
如果您想在任务完成后执行某项操作,可以使用如下方式继续:

private void MyMethod()
{
   var uiTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
   var myBackgroundTask = Task.Factory.StartNew(() => MyBackGroundMethod(uiTaskScheduler));
}

private void MyBackGroundMethod(TaskScheduler uiTaskScheduler)
{
    Task.Factory.StartNew(
            () => { TextBox1.Text = "Hello from separate thread"; },
            CancellationToken.None,
            TaskCreationOptions.None,
            uiTaskScheduler);
}
var finishedTask = myBackgroundTask.ContinueWith(
                    x => Label1.Text = "Task 1 completed sucessfully",
                    CancellationToken.None,
                    TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnRanToCompletion,
                    uiTaskScheduler);
请注意TaskContinuationOptions-您可以指定仅在没有错误时继续,或者仅在取消、未取消等情况下继续(更多)

如果希望取消长时间运行的进程,可以使用CancellationToken

下面是一个完整的示例,它使用后台任务,更新进度,允许取消,并在完成、出错、取消或完成时报告

它是一个具有2个按钮、1个标签和1个进度条的表单。分别命名为StartButton、StopButton、ProgressBar、InformationLabel

public partial class MainForm : Form
{
    CancellationTokenSource cancelTokenSource;

    public MainForm()
    {
        InitializeComponent();
    }

    private void StartButton_Click(object sender, EventArgs e)
    {
        InformationLabel.Text = "Task 1 running...";
        var uiTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
        cancelTokenSource = new CancellationTokenSource();

        this.StopButton.Enabled = true;
        this.StartButton.Enabled = false;

        var someWork = Task.Factory.StartNew(
            () => { DoWork(uiTaskScheduler); },
            cancelTokenSource.Token,
            TaskCreationOptions.None,
            TaskScheduler.Default);

        var someWorkFinished = someWork.ContinueWith(
                x => InformationLabel.Text = "Task 1 completed sucessfully",
                CancellationToken.None,
                TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnRanToCompletion,
                uiTaskScheduler);

        var someWorkErrored = someWork.ContinueWith(
                x => InformationLabel.Text = "Task 1 Errored",
                CancellationToken.None,
                TaskContinuationOptions.OnlyOnFaulted,
                uiTaskScheduler);

        var someWorkCancelled = someWork.ContinueWith(
                x => InformationLabel.Text = "Task 1 Cancelled",
                CancellationToken.None,
                TaskContinuationOptions.OnlyOnCanceled,
                uiTaskScheduler);

        var resultTasks = new List<Task>();
        resultTasks.Add(someWorkFinished);
        resultTasks.Add(someWorkErrored);
        resultTasks.Add(someWorkCancelled);

        Task.Factory.ContinueWhenAny(
            resultTasks.ToArray(),
            x => this.Reset(),
            CancellationToken.None,
            TaskContinuationOptions.None,
            uiTaskScheduler);
    }

    private void Reset()
    {
        this.StopButton.Enabled = false;
        this.StartButton.Enabled = true;
    }

    private void DoWork(TaskScheduler uiTaskScheduler)
    {
        for (int i = 0; i < 10; i++)
        {
            cancelTokenSource.Token.ThrowIfCancellationRequested();

            Thread.Sleep(500);
            i++;

            // Update progress
            Task.Factory.StartNew(
                () => { UpdateProgress(ProgressBar, i * 10); }, 
                CancellationToken.None, 
                TaskCreationOptions.None, 
                uiTaskScheduler);
        }
    }

    private void UpdateProgress(ProgressBar progressBar, int i)
    {
        progressBar.Value = i;
    }

    private void StopButton_Click(object sender, EventArgs e)
    {
        cancelTokenSource.Cancel();
    }
}
public分部类MainForm:Form
{
CancellationTokenSource cancelTokenSource;
公共表格(
{
初始化组件();
}
私有无效开始按钮单击(对象发送者,事件参数e)
{
InformationLabel.Text=“任务1正在运行…”;
var uiTaskScheduler=TaskScheduler.FromCurrentSynchronizationContext();
cancelTokenSource=新的CancellationTokenSource();
this.StopButton.Enabled=true;
this.StartButton.Enabled=false;
var someWork=Task.Factory.StartNew(
()=>{DoWork(uiTaskScheduler);},
cancelTokenSource.Token,
任务创建选项。无,
TaskScheduler.Default);
var someWorkFinished=someWork.ContinueWith(
x=>InformationLabel.Text=“任务1成功完成”,
取消令牌。无,
TaskContinuationOptions.Executes同步执行| TaskContinuationOptions.OnlyOnRanToCompletion,
uiTaskScheduler);
var someWorkErrored=someWork.ContinueWith(
x=>InformationLabel.Text=“任务1出错”,
取消令牌。无,
TaskContinuationOptions.OnlyOnFaulted,
uiTaskScheduler);
var someWorkCancelled=someWork.ContinueWith(
x=>InformationLabel.Text=“任务1已取消”,
取消令牌。无,
TaskContinuationOptions.Only已取消,
uiTaskScheduler);
var resultTasks=新列表();
resultTasks.Add(someWorkFinished);
结果任务添加(someWorkErrored);
resultTasks.Add(某些工作已取消);
Task.Factory.ContinueWhenAny(
resultTasks.ToArray(),
x=>this.Reset(),
取消令牌。无,
TaskContinuationOptions。无,
uiTaskScheduler);
}
私有无效重置()
{
this.StopButton.Enabled=false;
this.StartButton.Enabled=true;
}
专用无效工作(任务调度器uiTaskScheduler)
{
对于(int i=0;i<10;i++)
{
cancelTokenSource.Token.ThrowIfCancellationRequested();
睡眠(500);
i++;
//更新进度
Task.Factory.StartNew(
()=>{UpdateProgress(ProgressBar,i*10);},
取消令牌。无,
任务创建选项。无,
uiTaskScheduler);
}
}
私有void UpdateProgress(ProgressBar ProgressBar,inti)
{
progressBar.Value=i;
}
私有无效停止按钮\u单击(对象发送者,事件参数e)
{
cancelTokenSource.Cancel();
}
}

从非UI线程操作UI?你试过吗?你会得到一个异常.WPF还是Forms?这就是为什么我需要输入更多的问题?要回答您的问题,请归咎于它的形式,然后标记它,使其正确分类。在一个线程上,您不能同时执行两件事情。您可以在多个线程上一次在UI外部执行多个操作,但必须将对UI的更改排队,以便一次只执行一个更改。只需调用
BeginInvoke
()调用在UI线程上更改UI的代码即可。提供了一个很好的概述。你的权利彼得,我很高兴给你信用,如果你能发布你的评论作为一个答案。