C# 在窗体加载时启动后台线程

C# 在窗体加载时启动后台线程,c#,multithreading,winforms,backgroundworker,C#,Multithreading,Winforms,Backgroundworker,我需要向你寻求帮助,因为我已经为此挣扎太久了。 已经阅读了很多教程,但最终。。。没什么 因此,我有一个带有GetServicesToList()的ServiceProcess类。此方法使用服务列表填充服务对象 我现在正在做的是,在应用程序运行时读取一个缓存文件(带有服务),这将在datagridView中显示数据。按下表单按钮时也会调用GetServicesToList() 由于服务器可用性问题,此任务最多需要10分钟 在BackgroundWorker类的帮助下,我想要实现的是在运行时启动此方

我需要向你寻求帮助,因为我已经为此挣扎太久了。 已经阅读了很多教程,但最终。。。没什么

因此,我有一个带有GetServicesToList()的ServiceProcess类。此方法使用服务列表填充服务对象

我现在正在做的是,在应用程序运行时读取一个缓存文件(带有服务),这将在datagridView中显示数据。按下表单按钮时也会调用GetServicesToList()

由于服务器可用性问题,此任务最多需要10分钟

在BackgroundWorker类的帮助下,我想要实现的是在运行时启动此方法,每次完成后都会反复执行,以更新我的DataGridView以及更新缓存(outputFile)。 所有这些都不会让用户被这个过程打断

我试图在BackgroundWord_DoWork()中调用此方法,但由于我的ServiceProcess类使用ServiceBase(类ServicesProcess:ServiceBase),因此无法针对BackgroundWorker声明此方法

希望我已经用足够的细节表达了我自己,这样你们就能了解我想要实现的目标。如果有任何不清楚的地方,请询问详情

有人能帮我解决这个问题吗

public class ServicesProcess : ServiceBase, IEquatable<ServiceBase>
{
    private static string _machine = Services.GetServiceConfig();//ConfigurationManager.AppSettings.Get("machineName");
    private static List<Service> _servicesList;
    private static ServiceController[] _services;
    private List<ServiceController> _holder;
    private List<string> _configList;
    private static ObjectToSerialize _objectToSerialize;

    public List<Service> GetServicesToList()
    {
        //_services = ServiceController.GetServices(_machine);
        var result = MemoryCache.Default.Get(Name) as List<Service>;
        if (result != null)
            return result;

        try
        {

            _configList = new List<string>(Services.GetAllServicesConfig());
            _holder = new List<ServiceController>();
            foreach (string t in _configList)
            {
                _services = ServiceController.GetServices(t);
                _holder.AddRange(_services);
            }
        }
        catch (InvalidOperationException e)
        {

        }
        const string sPattern = "CSP";
        int i = 0;

        var cspServices = _holder.Where(x => x.DisplayName.Trim().StartsWith(sPattern)).ToList();

        _servicesList = new List<Service>();

        for (i = 0; i < cspServices.Count; i++)
        {
            Service obj = new Service
            {
                ServiceName = cspServices.ElementAt(i).DisplayName,
                ServiceVersion =
                    GetFileVersion(
                        GetFilePath(cspServices.ElementAt(i).ServiceName, cspServices.ElementAt(i).MachineName),
                        @"\\" + cspServices.ElementAt(i).MachineName + "\\"),
                ServiceStatus = cspServices.ElementAt(i).Status.ToString()
            };

            _servicesList.Add(obj);

        }

        _objectToSerialize = new ObjectToSerialize { Services = _servicesList };

        Serializer serializer = new Serializer();


        serializer.SerializeObject("outputFile.txt", _objectToSerialize);

        MemoryCache.Default.Set(Name, _servicesList, DateTimeOffset.Now.Add(new TimeSpan(0, 0, 30, 0)));

        return _servicesList;
    }
公共类服务流程:ServiceBase,IEquatable
{
私有静态字符串_machine=Services.GetServiceConfig();//ConfigurationManager.AppSettings.Get(“machineName”);
私有静态列表_servicesList;
专用静态ServiceController[]\u服务;
私人名单持有人;
私有列表\u配置列表;
私有静态ObjectToSerialize\u ObjectToSerialize;
公共列表GetServicesToList()
{
//_services=ServiceController.GetServices(\u机器);
var result=MemoryCache.Default.Get(Name)as List;
如果(结果!=null)
返回结果;
尝试
{
_configList=新列表(Services.GetAllServicesConfig());
_holder=新列表();
foreach(配置列表中的字符串t)
{
_services=ServiceController.GetServices(t);
_holder.AddRange(_服务);
}
}
捕获(无效操作异常)
{
}
常量字符串sPattern=“CSP”;
int i=0;
var cspServices=_holder.Where(x=>x.DisplayName.Trim().StartsWith(sPattern)).ToList();
_servicesList=新列表();
对于(i=0;i
这就是获取所有服务的方法。现在在设计类中,我想使用这个方法,因为线程、任务或后台工作,所以这个方法将作为后台进程执行。不知道如何做

为了帮助你形象化应用程序本身。。。
我不能完全确定您的目标,但是如果
GetServicesToList()
应该在后台线程中运行,您就不能实现
async
/
wait

public async Task<List<Service>> GetServicesToList()
{
    return await Task.Run(() => {
        // all your old code
    });
}
我假设您正在进行某种数据绑定,因此当
serviceList
水合时,只需将其传递给视图


这是一个独立的概念

using System;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main()
        {
            SimulateTenButtonClicks();
            Console.ReadKey();
        }

        private static async void SimulateTenButtonClicks()
        {
            var foo = new Foo();
            for (var i = 0; i < 10; i++)
            {
                var result = foo.DoStuff(i);
                Console.WriteLine(await result);
            }
        }

        public class Foo
        {
            public async Task<string> DoStuff(int i)
            {
                await Task.Delay(500); // simulate load
                return await Task.Run(() =>
                {
                    return String.Format("I have been hit {0} times", i);
                });
            }
        }
    }
}
使用系统;
使用System.Threading.Tasks;
命名空间控制台应用程序1
{
班级计划
{
静态void Main()
{
SimulatedButtonClicks();
Console.ReadKey();
}
私有静态异步void simulatedButtonClicks()
{
var foo=new foo();
对于(变量i=0;i<10;i++)
{
var结果=foo.DoStuff(i);
控制台写入线(等待结果);
}
}
公开课Foo
{
公共异步任务DoStuff(inti)
{
等待任务。延迟(500);//模拟负载
返回等待任务。运行(()=>
{
返回String.Format(“我被击中{0}次”,I);
});
}
}
}
}

创建一个线程或任务。我是.NET新手。我确实使用async和await方法研究了线程,但没有深入研究。ServiceBase用于服务,而不是桌面应用程序。我认为您在这方面走错了方向。我还建议您使用一个简单的任务。Run()现在。我正在使用ServiceBase类查找ServiceName。好吧……现在我开始担心了。更新包括更多的解释和一些代码。为什么要继续?在UI线程中设置字段不是问题-事实上,从单个线程设置和检查标志更安全。代码也会更干净。@Panagiotiskanavo这不是必需的,但我只是想找出一种方法来防止不必要的多次执行。如果这是一个10分钟的作业,并且是通过按下按钮启动的,你不希望用户连续按5次按钮。我通常会将所有这些连接到一个ICommand中。它说不能将bool类型转换为of类型List@Jakubee,我简化了它,我有了延续无论如何都是错的。好吧。这让我走上了正确的轨道。如果我想经常这样做呢。我的意思是,让这个任务更新文件ove
using System;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main()
        {
            SimulateTenButtonClicks();
            Console.ReadKey();
        }

        private static async void SimulateTenButtonClicks()
        {
            var foo = new Foo();
            for (var i = 0; i < 10; i++)
            {
                var result = foo.DoStuff(i);
                Console.WriteLine(await result);
            }
        }

        public class Foo
        {
            public async Task<string> DoStuff(int i)
            {
                await Task.Delay(500); // simulate load
                return await Task.Run(() =>
                {
                    return String.Format("I have been hit {0} times", i);
                });
            }
        }
    }
}