C# 使用Task.Run()调用方法时,它必须是异步方法吗?

C# 使用Task.Run()调用方法时,它必须是异步方法吗?,c#,xamarin,xamarin.forms,async-await,task,C#,Xamarin,Xamarin.forms,Async Await,Task,我的代码如下所示: async public Task Btn(int pts) { switch (Settings.mode) { case MO.Assign: case MO.Learn: break; case MO.Quiz: await Task.Run(() => App.DB.Increme

我的代码如下所示:

    async public Task Btn(int pts)
    {
        switch (Settings.mode)
        {
            case MO.Assign:
            case MO.Learn:
                break;
            case MO.Quiz:
                await Task.Run(() => App.DB.IncrementPoints(phrase, 1));
                await Task.Delay(250);
                break;
            case MO.Practice:
                Device.BeginInvokeOnMainThread(() =>
                {
                    vm.Points = new String('☆', phrase.Points + pts);
                });
                await Task.Run(() =>
                {
                    App.DB.IncrementPoints(phrase, pts);
                    App.DB.IncrementHistory(HIST.Views);
                });
                await Task.Delay(250);
                break;
        }
        App.selectedPhrases = null;
        timer2Seconds = 2;
    }


    public void IncrementPoints(Phrase phrase, int pts)
    {
        lock (l)
        {
            db2.Execute("UPDATE phrase SET Points = Points + " + pts +
                        " WHERE PhraseId = '" + phrase.PhraseId + "'");
        }
    }
vm.Points = new String('☆', phrase.Points + pts);

await Task.Run(() =>
{
    App.DB.IncrementPoints(phrase, pts);
    App.DB.IncrementHistory(HIST.Views);
});
await Task.Delay(250);
我对这个任务有点困惑。快跑,等待。首先,我想让它更新屏幕:

vm.Points = new String('☆', phrase.Points + pts);
然后我希望数据库更新,然后有一个250毫秒的延迟


但是我的方法IncrementPoints不是异步方法可以吗?

我不太确定您想做什么,但要回答您的问题:

但是我的方法IncrementPoints不是异步方法,可以吗

是的,没关系,这也是
任务的目的之一。运行
。您可以使用
Task.Run
将同步操作转换为可等待的异步操作。因此,应该在lambda中放置非异步方法。如果
IncrementPoints
是异步的,您就不需要
Task.Run
,因为您可以执行以下操作:

await IncrementPoints(...);
您的代码应该是这样的:

    async public Task Btn(int pts)
    {
        switch (Settings.mode)
        {
            case MO.Assign:
            case MO.Learn:
                break;
            case MO.Quiz:
                await Task.Run(() => App.DB.IncrementPoints(phrase, 1));
                await Task.Delay(250);
                break;
            case MO.Practice:
                Device.BeginInvokeOnMainThread(() =>
                {
                    vm.Points = new String('☆', phrase.Points + pts);
                });
                await Task.Run(() =>
                {
                    App.DB.IncrementPoints(phrase, pts);
                    App.DB.IncrementHistory(HIST.Views);
                });
                await Task.Delay(250);
                break;
        }
        App.selectedPhrases = null;
        timer2Seconds = 2;
    }


    public void IncrementPoints(Phrase phrase, int pts)
    {
        lock (l)
        {
            db2.Execute("UPDATE phrase SET Points = Points + " + pts +
                        " WHERE PhraseId = '" + phrase.PhraseId + "'");
        }
    }
vm.Points = new String('☆', phrase.Points + pts);

await Task.Run(() =>
{
    App.DB.IncrementPoints(phrase, pts);
    App.DB.IncrementHistory(HIST.Views);
});
await Task.Delay(250);

我不确定你想做什么,但要回答你的问题:

但是我的方法IncrementPoints不是异步方法,可以吗

是的,没关系,这也是
任务的目的之一。运行
。您可以使用
Task.Run
将同步操作转换为可等待的异步操作。因此,应该在lambda中放置非异步方法。如果
IncrementPoints
是异步的,您就不需要
Task.Run
,因为您可以执行以下操作:

await IncrementPoints(...);
您的代码应该是这样的:

    async public Task Btn(int pts)
    {
        switch (Settings.mode)
        {
            case MO.Assign:
            case MO.Learn:
                break;
            case MO.Quiz:
                await Task.Run(() => App.DB.IncrementPoints(phrase, 1));
                await Task.Delay(250);
                break;
            case MO.Practice:
                Device.BeginInvokeOnMainThread(() =>
                {
                    vm.Points = new String('☆', phrase.Points + pts);
                });
                await Task.Run(() =>
                {
                    App.DB.IncrementPoints(phrase, pts);
                    App.DB.IncrementHistory(HIST.Views);
                });
                await Task.Delay(250);
                break;
        }
        App.selectedPhrases = null;
        timer2Seconds = 2;
    }


    public void IncrementPoints(Phrase phrase, int pts)
    {
        lock (l)
        {
            db2.Execute("UPDATE phrase SET Points = Points + " + pts +
                        " WHERE PhraseId = '" + phrase.PhraseId + "'");
        }
    }
vm.Points = new String('☆', phrase.Points + pts);

await Task.Run(() =>
{
    App.DB.IncrementPoints(phrase, pts);
    App.DB.IncrementHistory(HIST.Views);
});
await Task.Delay(250);

我对刚刚删除的一条评论的回复是:谢谢你的意见。我使用它是因为我认为这可能是最好的方法,但根据你刚才所说的,也许这太过分了。使用Task.Run执行此操作是否有任何开销或问题?如果你要做编码,你会在没有等待和任务的情况下调用它吗?请注意,我在Points表中有大约15000行,但我确实在PhraseId上有一个索引。当您从主线程调用(等待)它时,则不需要BeginInvokeOnMainThread()。最好的解决方案是当App.DB提供异步方法时:删除任务。运行althogether并等待I/O。为什么
lock()
在该方法中?就BeginInvoke而言,这取决于您如何调用它。显示完整的调用堆栈(缩写)。顶层应该是一个
异步void
事件处理程序。下面sweeper的回答是正确的。我对刚刚删除的评论的回复是:谢谢你的输入。我使用它是因为我认为这可能是最好的方法,但根据你刚才所说的,也许这太过分了。使用Task.Run执行此操作是否有任何开销或问题?如果你要做编码,你会在没有等待和任务的情况下调用它吗?请注意,我在Points表中有大约15000行,但我确实在PhraseId上有一个索引。当您从主线程调用(等待)它时,则不需要BeginInvokeOnMainThread()。最好的解决方案是当App.DB提供异步方法时:删除任务。运行althogether并等待I/O。为什么
lock()
在该方法中?就BeginInvoke而言,这取决于您如何调用它。显示完整的调用堆栈(缩写)。顶层应该是一个
异步void
事件处理程序。下面的sweeper给出的答案是正确的。