今天在群裡,有人問
有幾個void返回值的方法,但是我想讓這幾個方法有執行順序,要怎麼處理,ABCD 四個方法,依次執行,但是這幾個方法都是無返回值的
這個問題其實很簡單,如果方法是同步方法,直接四個方法連續寫就好了,比如:
static void Main()
{
A();
B();
C();
D();
}
但是如果方法裡面包含了耗時操作,那麼四個這樣寫就有問題了,執行順序就錯掉了,我們需要利用callback函式來進行操作,但是本著能不動原方法就不動的理念,我們使用Task的OnCompleted事件(.net framework中可以使用BeginInvoke(callback,null))來做處理
- 如果方法有返回值,則使用Func,或者Func<>
- 如果方法沒有返回值,則使用Action,或者Action<>
1. 無返回值在.net core中使用Task的OnCompleted事件
由於是沒有返回值的方法,我們使用
例如
static void Main()
{
Action action1 = () => {
Thread.Sleep(1000);
Console.WriteLine("action1");
};
Action action2 = () => {
Thread.Sleep(2000);
Console.WriteLine("action2");
};
Action action3 = () => {
Thread.Sleep(3000);
Console.WriteLine("action3");
};
Action action4 = () => {
Thread.Sleep(3000);
Console.WriteLine("action4");
};
Stack st = new Stack();
st.Push(action2);
st.Push(action3);
st.Push(action4);
void MyAsynCallback()
{
if (st.Count > 0)
{
var action = (Action)st.Pop();
Task.Run(action).GetAwaiter().OnCompleted(() =>
{
MyAsynCallback();
});
}
}
Task.Run(action1).GetAwaiter().OnCompleted(() =>
{
MyAsynCallback();
});
Console.ReadLine();
//Stack的Pop是先進後出,輸出順序action1 action4 action3 action2
}
我們可以將Stack改成其他的,比如List、Queue等,自行判斷是否需要手動彈出action即可
2. 無返回值在.net framework中使用BeginInvoke
static void Main()
{
Action action1 = () => {
Thread.Sleep(1000);
Console.WriteLine("action1");
};
Action action2 = () => {
Thread.Sleep(2000);
Console.WriteLine("action2");
};
Action action3 = () => {
Thread.Sleep(3000);
Console.WriteLine("action3");
};
Action action4 = () => {
Thread.Sleep(3000);
Console.WriteLine("action4");
};
Stack st = new Stack();
st.Push(action2);
st.Push(action3);
st.Push(action4);
void MyAsynCallback(IAsyncResult async)
{
if (st.Count > 0)
{
var action = (Action)st.Pop();
action.BeginInvoke(new AsyncCallback(MyAsynCallback),null);
}
}
action1.BeginInvoke(new AsyncCallback(MyAsynCallback), null);
Console.ReadLine();
//Stack的Pop是先進後出,輸出順序action1 action4 action3 action2
}
3. 有返回值在.net core中使用Task的OnCompleted事件
由於是沒有返回值的方法,我們使用
例如
static void Main()
{
Func<int> func1 = () => {
Thread.Sleep(1000);
Console.WriteLine("func1");
return 1;
};
Func<int> func2 = () => {
Thread.Sleep(2000);
Console.WriteLine("func2");
return 1;
};
Func<int> func3 = () => {
Thread.Sleep(3000);
Console.WriteLine("func3");
return 0;
};
Func<int> func4 = () => {
Thread.Sleep(3000);
Console.WriteLine("func4");
return 1;
};
Stack st = new Stack();
st.Push(func2);
st.Push(func3);
st.Push(func4);
void MyAsynCallback(int result)
{
if (st.Count > 0 && result > 0)
{
var action = (Func<int>)st.Pop();
var task1 = Task.Run(action);
task1.GetAwaiter().OnCompleted(() =>
{
MyAsynCallback(task1.Result);
});
}
}
var task = Task.Run(func1);
task.GetAwaiter().OnCompleted(() =>
{
MyAsynCallback(task.Result);
});
Console.ReadLine();
//Stack的Pop是先進後出,輸出順序func1 func4 func3 func2
}
4. 有返回值在.net framework中使用BeginInvoke
delegate int dele_func(int a);
static void Main()
{
Func<int> func1 = () => {
Thread.Sleep(1000);
Console.WriteLine("func1");
return 1;
};
Func<int> func2 = () => {
Thread.Sleep(2000);
Console.WriteLine("func2");
return 1;
};
Func<int> func3 = () => {
Thread.Sleep(3000);
Console.WriteLine("func3");
return 1;
};
Func<int> func4 = () => {
Thread.Sleep(3000);
Console.WriteLine("func4");
return 1;
};
Stack st = new Stack();
st.Push(func2);
st.Push(func3);
st.Push(func4);
void MyAsynCallback(IAsyncResult async)
{
dele_func dele_Func2 = (dele_func)async.AsyncState;
int result = dele_Func2.EndInvoke(async);
if (st.Count > 0 && result > 0)
{
var action = (Func<int>)st.Pop();
dele_func dele_Func1 = new dele_func((int a) => { return action.Invoke(); });
IAsyncResult asyncResult1 = dele_Func1.BeginInvoke(0, new AsyncCallback(MyAsynCallback), dele_Func1);
}
}
dele_func dele_Func = new dele_func((int a) => { return func1.Invoke(); });
IAsyncResult asyncResult = dele_Func.BeginInvoke(0, new AsyncCallback(MyAsynCallback), dele_Func);
Console.ReadLine();
//Stack的Pop是先進後出,輸出順序func1 func4 func3 func2
}
有返回值時,可以根據result的判斷,來判斷是否繼續往下執行
如有問題,歡迎指正