如何从函数返回值但保持函数“活动”c#

时间:2016-06-01 10:49:14

标签: c# function return

我在我创建的DLL中有一个函数,它执行SQL命令并返回执行它们的路径文件,有错误的命令数和3 pos中成功执行的命令数。阵列。 问题是它只会在foreach结束时返回,只允许我以最后执行文件的形式出现在文本框中,并且我需要在执行时显示文件路径。

  

我需要一种方法在每次foreach迭代时返回数组,但保持>函数处于活动状态,以便执行下一个>文件中的其余命令,这是函数:

public string[] ExecuteCommands(string Directoria, CdpsiUpdateSql Updater, CdpsiUpdateSqlparser parser, string Log)
        {

            string[] numArray1 = new string[3];
            List<string> list = ((IEnumerable<string>)Directory.GetFiles(Directoria, "*.sql", SearchOption.TopDirectoryOnly)).Select(f =>
            {
                string[] strArray = Path.GetFileName(f).Split('_');
                int result;
                if (strArray.Length < 1 || !int.TryParse(strArray[0], out result))
                    result = -1;
                var data = new
                {
                    File = f,
                    Version = result
                };
                return data;
            }).Where(f => f.Version > -1).OrderBy(f => f.Version).Select(f => f.File).ToList<string>();
            foreach (string str in list)
            {
                int[] numArray2 = this.ExecuteCommand(parser.Parser(str), Updater, str, Log);
                int Certos = Convert.ToInt32(numArray1[0]);
                int Errados = Convert.ToInt32(numArray1[1]);
                Certos  += numArray2[0];
                Errados += numArray2[1];
                numArray1[0] = Certos.ToString();
                numArray1[1] = Errados.ToString();
                numArray1[2] = str;

            }
            return numArray1;
        }

任何帮助都会得到很好的帮助,谢谢

使用yield?

public IEnumerable<string []> ExecuteCommands(string Directoria, CdpsiUpdateSql Updater, CdpsiUpdateSqlparser parser, string Log)
        {

            string[] numArray1 = new string[3];
            List<string> list = ((IEnumerable<string>)Directory.GetFiles(Directoria, "*.sql", SearchOption.TopDirectoryOnly)).Select(f =>
            {
                string[] strArray = Path.GetFileName(f).Split('_');
                int result;
                if (strArray.Length < 1 || !int.TryParse(strArray[0], out result))
                    result = -1;
                var data = new
                {
                    File = f,
                    Version = result
                };
                return data;
            }).Where(f => f.Version > -1).OrderBy(f => f.Version).Select(f => f.File).ToList<string>();
            foreach (string str in list)
            {
                int[] numArray2 = this.ExecuteCommand(parser.Parser(str), Updater, str, Log);
                int Certos = Convert.ToInt32(numArray1[0]);
                int Errados = Convert.ToInt32(numArray1[1]);
                Certos  += numArray2[0];
                Errados += numArray2[1];
                numArray1[0] = Certos.ToString();
                numArray1[1] = Errados.ToString();
                numArray1[2] = str;
                yield return numArray1;
            }
            //return numArray1;
        }

3 个答案:

答案 0 :(得分:2)

首先,我会为结果定义一个更好的类型:

g_signal_connect(splitmuxsink, "format-location",
                    G_CALLBACK (on_format_location), NULL);
...

gchar* on_format_location(GstSplitMuxSink *splitmux, guint fragment_id,
            gpointer user_data);

然后你可以在你的dll方法中添加一个IProgress<T>参数: 并将此作为dll方法的额外参数:

error: unknown type name ‘GstSplitMuxSink’

调用网站上,您可以像这样创建Progress<T>的实例:

public struct Result
{
    public string File;
    public int Errors;
    public int Successes;
}

并实现类似的public void ExecuteCommands(string Directoria, CdpsiUpdateSql Updater, CdpsiUpdateSqlparser parser, string Log, IProgress<Result> progress) { //... your code foreach (string str in list) { int[] numArray2 = this.ExecuteCommand(parser.Parser(str), Updater, str, Log); // your code Result result = new Result { File = str, Error = Errados, Successes = Certos }; progress.Report(result); } } 方法:

Progress<Result> progress = new Progress<Result>(HandleProgress);
ExecuteCommands(Directoria, Updater, parser, Log, progress);

注意但是HandleProgress同步运行 。因此,您的UI线程被阻止,并且不会立即绘制对控件的更改。因此我添加了private void HandleProgress(Result result) { /* use the values in result to update your UI */ Refresh(); // refresh the controls you updated } 语句,但其确切的实现取决于您即将更新的控件。

ExecuteCommands方法也很好。但我仍然会建议一个合适的Refresh()类型。您的方法的使用者永远不会知道该字符串数组中包含哪些信息。被阻止的UI线程的问题将是相同的。

答案 1 :(得分:0)

您可以将return语句移动到foreach循环中并使用yield

foreach (string str in list)
            {
                int[] numArray2 = this.ExecuteCommand(parser.Parser(str), Updater, str, Log);
                int Certos = Convert.ToInt32(numArray1[0]);
                int Errados = Convert.ToInt32(numArray1[1]);
                Certos  += numArray2[0];
                Errados += numArray2[1];
                numArray1[0] = Certos.ToString();
                numArray1[1] = Errados.ToString();
                numArray1[2] = str;

                yield return numArray1;
            }

答案 2 :(得分:0)

只是为您提供一些替代方案。您可以尝试使用delegate / lambda

public void ExecuteCommands(string Directoria, CdpsiUpdateSql Updater, CdpsiUpdateSqlparser parser, string Log, Action<int[]> getResults)
{

    string[] numArray1 = new string[3];
    List<string> list = ((IEnumerable<string>)Directory.GetFiles(Directoria, "*.sql", SearchOption.TopDirectoryOnly)).Select(f =>
    {
        string[] strArray = Path.GetFileName(f).Split('_');
        int result;
        if (strArray.Length < 1 || !int.TryParse(strArray[0], out result))
            result = -1;
        var data = new
        {
            File = f,
            Version = result
        };
        return data;
    }).Where(f => f.Version > -1).OrderBy(f => f.Version).Select(f => f.File).ToList<string>();
    foreach (string str in list)
    {
        int[] numArray2 = this.ExecuteCommand(parser.Parser(str), Updater, str, Log);
        int Certos = Convert.ToInt32(numArray1[0]);
        int Errados = Convert.ToInt32(numArray1[1]);
        Certos += numArray2[0];
        Errados += numArray2[1];
        numArray1[0] = Certos.ToString();
        numArray1[1] = Errados.ToString();
        numArray1[2] = str;

        //new code
        if(getResults!=null)
        {
            getResults(numArray1);
        }
    }

}

主要电话中的用法将是:

int totalResults=0;
Action<int[]> doSomething = (results)=>
    {
        //do some work whenever results is returned, e.g
        totalResults+=results.Sum();
    };
ExecuteCommands(directoria, parser, updater, log, doSomething);