我有一个长期运行的功能"需要在计时器上触发,我也希望能够通过按钮点击触发。任务正在运行时,按钮将切换为“取消”按钮。按钮。我只希望一次运行一个任务的单个实例。我已将任务设为私有变量,以便计时器可以检查任务的IsCompleted
状态。为此,我创建了一个私有变量
private Task sync;
然后我有一个执行任务的功能
private async Task syncUsers()
{
//
}
现在,点击按钮,我将变量分配给函数
sync = syncUsers();
await sync;
似乎任务完成时就是这样。如何重新启动任务/功能?我尝试使用任务工厂和异步委托,但没有工作。
sync = Task.Factory.StartNew(async delegate { await syncStudents(); });
await sync;
我有一种感觉,我完全错了但不知道从哪里开始。
答案 0 :(得分:0)
你无法重新开始。您必须创建新任务。如果您想支持多个并行任务执行而不是Task sync
,请执行List<Task> syncTasks
,然后执行syncTasks.Add(syncUsers())
。然后,您可以在await
上Task.WhenAll(syncTasks)
。
除非我误解了这个问题
修改强> 要定期运行同步任务,请执行以下操作:
private System.Threading.Timer _syncTimer;
private bool _isRunning;
private int refreshInterval = 30;
public YourClass(){
_syncTimer = new System.Threading.Timer(TimerCallback);
}
public void StartSyncTimer(){
_syncTimer.Change(0, 0);
}
private async Task SyncUsers(){
//
}
private void TimerCallback(object userState){
_isRunning = true;
var task = SyncUsers();
task.ContinueWith(t => {
_isRunning = false;
_syncTimer.Change(TimeSpan.FromSeconds(refreshInterval), TimeSpan.FromSeconds(0));
});
}
然后在您的Click处理程序中,您可以执行以下操作:
if(!_isRunning){
_syncTimer.Change(0,0);
}
说明:在构造函数中,我们初始化一个定期执行TimerCallback
方法的System.Threading.Timer实例。
然后我们在类中添加一个公共方法来立即启动定时器执行:_syncTimer.Change(0,0)。这里第一个零表示第一次执行(立即)之前的延迟,第二个零表示重复间隔。它也是零意味着它不会自动重复。
然而,在继续执行SyncUsers任务时,我们会将计时器重新安排到您想要的任何时间段。
在计时器回调中,我们还将_IsRunning设置为true以提醒任何感兴趣的各方状态,然后在任务完成时我们将其设置为true。
上面代码的行为是:如果同步任务是由计时器启动的,那么单击将不会执行任何操作,因为_isRunning将为true;如果同步是在完成refreshIntervals
之后完成的,则点击将立即执行同步,然后完成将重新安排同步以供以后使用。
免责声明:我实际上并没有运行上面的代码,但这是我已经完成了数百次的工作,可以让我们付出更多的努力。
答案 1 :(得分:0)
private Task sync;
private readonly object syncLock = new object();
private Task syncUsers()
{
lock (syncLock)
{
if (this.sync == null || this.sync.IsCompleted)
{
this.sync = ...
}
}
return this.sync;
}
答案 2 :(得分:-1)
让我们假设您在创建任务时执行类似
的操作Task task = new Task(()=>{ DoStuff(); });
您需要做的是,不保留任务以便以后执行。您需要保留委托,并在以后使用相同的委托创建另一个任务。
如果你不确定如何,查看Action<T>
,它可能会给你一些想法。