当我在Thread.Sleep
程序freez中使用UpdateGuItemsAsync
10秒钟,因为线程被阻止了。如果我在'UpdateGuItemsAsync'中使用Task.Delay
,代码会立即执行而不会暂停。我希望在没有UI冻结的列表更新之前得到延迟。如何在.net 3.5中执行此操作?
TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(UpdateGuItemsAsync, CancellationToken.None, TaskCreationOptions.None, uiScheduler);
public void UpdateGuItemsAsync()
{
System.Threading.Thread.Sleep(10000);
for (int i = 0; i < 100; i++)
{
Gu45Document gu45Document = new Gu45Document();
gu45Document.Form = "EU-45";
Gu45Documents.Add(gu45Document);
}
}
答案 0 :(得分:3)
您可以使用System.Windows.Forms.Timer,等待10秒后不会阻止用户界面:
public void UpdateGuItemsAsync()
{
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
timer.Interval = 10000;
timer.Tick += (sender, args) =>
{
timer.Stop();
for (int i = 0; i < 100; i++)
{
Gu45Document gu45Document = new Gu45Document();
gu45Document.Form = "EU-45";
Gu45Documents.Add(gu45Document);
}
};
timer.Start();
}
答案 1 :(得分:1)
修改强>
抱歉,我错过了关于.Net 3.5导致Task.Delay谈话的观点。下面找到.net 3.5中的一个示例,它在10秒后更新表单中的进度条。当按下那种形式的按钮时:
using System;
using System.Threading;
using System.Windows.Forms;
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
delegate void UpdateGuItemsAsyncDelegate();
void UpdateGuItemsAsync()
{
for (int i = 0; i < 100; i++)
{
progressBar1.PerformStep();
}
}
private void button1_Click(object sender, EventArgs e)
{
ThreadPool.QueueUserWorkItem(state =>
{
Thread.Sleep(10000);
if (progressBar1.InvokeRequired)
{
UpdateGuItemsAsyncDelegate del = new UpdateGuItemsAsyncDelegate(UpdateGuItemsAsync);
this.Invoke(del);
}
else
{
UpdateGuItemsAsync();
}
});
}
}
在WPF / XAML中,如果窗口中有进度条和按钮,则几乎可以执行相同操作:
<StackPanel>
<ProgressBar Name="ProgBar" Minimum="0" Maximum="100" Height="20" />
<Button Name="UpdateCmd" Click="UpdateCmd_Click" Content="Update" />
</StackPanel>
在代码中:
private void UpdateCmd_Click(object sender, RoutedEventArgs e)
{
ThreadPool.QueueUserWorkItem(state =>
{
Thread.Sleep(10000);
for (int i = 0; i < 100; i++)
{
Dispatcher.Invoke(new Action(() =>
{
ProgBar.Value++;
}));
Thread.Sleep(50);
}
});
}
答案 2 :(得分:1)
在你的情况下,我要做的是使用System.Windows.Threading.DispatcherTimer
让它在10秒后运行一个事件。这将适用于WPF和WinForms,但是如果您的项目是winforms,则需要在项目引用中添加对WindowsBase
的引用。
private void UpdateGuItemsAsync()
{
//This line must be called on the UI thread
var timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(10);
timer.Tick += OnUpdateGuiItemsTimerTick;
timer.Start();
}
private void OnUpdateGuiItemsTimerTick(object sender, EventArgs e)
{
//Stop the timer.
var timer = sender as DispatcherTimer;
timer.Stop();
//Run the code you where waiting for.
for (int i = 0; i < 100; i++)
{
Gu45Document gu45Document = new Gu45Document();
gu45Document.Form = "EU-45";
Gu45Documents.Add(gu45Document);
}
}
下面是一个独立程序,您可以在.NET 3.5中运行以查看它是否有效。您需要做的就是创建一个新的Windows窗体项目,添加对WindowsBase
的引用并使用下面的代码
using System;
using System.Windows.Forms;
using System.Windows.Threading;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Load += Form1_Load;
}
private void Form1_Load(object sender, EventArgs e)
{
UpdateGuiItems();
}
private void UpdateGuiItems()
{
var timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(5);
timer.Tick += OnUpdateGuiItemsTimerTick;
timer.Start();
}
private void OnUpdateGuiItemsTimerTick(object sender, EventArgs e)
{
var timer = sender as DispatcherTimer;
timer.Stop();
MessageBox.Show("Am I on the UI thread: " + !this.InvokeRequired);
}
}
}
答案 3 :(得分:0)
这应该做的工作
TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew( () => Thread.Sleep( 10000 ) )
.ContinueWith(
t => UpdateGuItemsAsync(),
CancellationToken.None,
TaskContinuationOptions.None,
uiScheduler );
public void UpdateGuItemsAsync()
{
// System.Threading.Thread.Sleep(10000);
for (int i = 0; i < 100; i++)
{
Gu45Document gu45Document = new Gu45Document();
gu45Document.Form = "EU-45";
Gu45Documents.Add(gu45Document);
}
}
我正在使用NuGet包Task Parallel Library for .NET 3.5。