iT邦幫忙

0

C# Task 不可在已經完成的工作上呼叫 start

c#
  • 分享至 

  • xImage

目前在作Quartz的部分
想讓別人包成Task或是傳functionName找出他的function
然後在傳到job內去Run
但目前第一次進入沒問題 第二次開始就會跳出
不可在已經完成的工作上呼叫start

每次執行完取消該任務可以嗎 另外該怎寫會比較好

public Task ReflectionFucntion(string ControllerName, string FunctionName)
{
    return new Task(() =>
    {
        Type type = Type.GetType(QuartzConst.TASK_NAMESPACE + ControllerName);
        //創建 {ControllerName} 類型的實例 {obj}
        var obj = Activator.CreateInstance(type);
        //取得 {FunctionName} 方法
        MethodInfo method = type.GetMethod(FunctionName);
        //調用 {FunctionName} 方法
        method.Invoke(obj, new object[] { });
    });
}

第一種 dataMap[QuartzConst.TASK_KEY] = new Task(() => { testFunction(); });
第二種 dataMap[QuartzConst.TASK_KEY] = ReflectionFucntion("Controller", "testFunction");

public class JobExecute : IJob
{
    public async Task Execute(IJobExecutionContext context)
    {
        var dataMap = context.JobDetail.JobDataMap;
        Task task = (Task)dataMap[QuartzConst.TASK_KEY];

        await Task.Run(() =>
        {
            try
            {
                task.Start();
            }
            catch (Exception e)
            {
                // e = "不可在已經完成的工作上呼叫start"
            }
        });
    }
}
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 個回答

0
rain_yu
iT邦研究生 5 級 ‧ 2024-02-02 09:03:32

在你的程式碼中,出現 "不可在已經完成的工作上呼叫start" 的問題是因為你試圖在已經完成的 Task 上調用 Start() 方法。一旦 Task 完成,它就無法再次啟動。此外,你也可以在每次任務執行完畢後取消該任務。

以下是修改後的程式碼,解決了這些問題:

public Task ReflectionFucntion(string ControllerName, string FunctionName)
{
    return Task.Run(() =>
    {
        Type type = Type.GetType(QuartzConst.TASK_NAMESPACE + ControllerName);
        //創建 {ControllerName} 類型的實例 {obj}
        var obj = Activator.CreateInstance(type);
        //取得 {FunctionName} 方法
        MethodInfo method = type.GetMethod(FunctionName);
        //調用 {FunctionName} 方法
        method.Invoke(obj, new object[] { });
    });
}

public class JobExecute : IJob
{
    public async Task Execute(IJobExecutionContext context)
    {
        var dataMap = context.JobDetail.JobDataMap;
        Task task = (Task)dataMap[QuartzConst.TASK_KEY];
        
        if (task.Status != TaskStatus.Running && task.Status != TaskStatus.WaitingToRun)
        {
            await Task.Run(() =>
            {
                try
                {
                    task = ReflectionFucntion("Controller", "testFunction");
                    task.Start();
                }
                catch (Exception e)
                {
                    // 處理例外狀況
                }
            });
        }
    }
}

在修改後的程式碼中,我們使用 task.Status 屬性檢查 Task 的狀態,確保只有在 Task 還沒開始或正在運行時才執行該任務。如果 Task 已經完成,則會建立並啟動一個新的 Task。同時,你也可以在每次任務執行完畢後取消該任務,可以使用 task.Dispose() 或其他適合的取消方法。

請注意,這只是一種解決方案,你可能需要根據你的需求進一步調整。

0
念戀
iT邦新手 4 級 ‧ 2024-02-06 17:10:31

原因可能是因爲你的dataMap[QuartzConst.TASK_KEY]是全域變數
第二次呼叫沒有出現 “不可在已經完成的工作上呼叫start”

//Program.cs 
    static async Task Main(string[] args)
    {
        //呼叫Execute
        TestNamespace A = new TestNamespace();
        await A.Execute();
        await A.Execute();
    }

//方法的檔案
public class TestNamespace
{
    //全域變數測試
    private static Task _task ;
    public async Task Execute()
    {

        Task task = ReflectionFucntion("ConsoleApp1.TestQuartz", "Test1");
        try
        {
            await Task.Run(() =>
             {
                task.Start();
             });
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
    }
    public static Task ReflectionFucntion(string ClassName, string FunctionName)
    {

        Task task = new Task(() =>
        {
            Type type = Type.GetType(ClassName);
            //創建 {ClassName} 類型的實例 {obj}
            var obj = Activator.CreateInstance(type);
            //取得 {FunctionName} 方法
            MethodInfo method = type.GetMethod(FunctionName);
            //調用 {FunctionName} 方法
            method.Invoke(obj, new object[] { });
        });

        return task;
    }
}

調整使用全域變數 此時呼叫2次會出現 “不可在已經完成的工作上呼叫start”

        //全域變數測試
        private static Task _task = ReflectionFucntion("ConsoleApp1.TestQuartz", "Test1");
        public async Task Execute()
        {

            Task task = _task;
            try
            {
                await Task.Run(() =>
                        {

                    task.Start();

                });
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }

我要發表回答

立即登入回答