如何管理加载动画线程? - C#

时间:2017-07-22 20:27:23

标签: c# multithreading forms visual-studio

我正在尝试加载表单。所以我放了一个GIF动画来做加载效果。

当我使用loading.Visible = true属性时,会发生这种情况,直到点击事件结束才会显示。

这是代码。

Private void btnLogin_Click (object sender, EventArgs e)
{
     loading.Visible = true;
     if (ConnectDataBase())
     {
         OpenForm2();
         This.Close();
     }
     else MessageBox.Show ("User or password, incorrect");
     loading.Visible = false;
}

数据库需要3至6秒才能在ConnectDataBase()函数中响应,但在事件结束前gif不会显示。

有人可以告诉我,我怎么能这样做?

2 个答案:

答案 0 :(得分:1)

为了使其工作,您需要在另一个线程上调用ConnectDataBase()。一种方法是:

private void btnLogin_Click(object sender, EventArgs e)
{
    loading.Visible = true;
    Task.Run<bool>(() =>
        {
            return ConnectDataBase();
        })
        .ContinueWith(t =>
        {
            if (t.Result)
            {
                OpenForm2();
                this.Close();
            }
            else MessageBox.Show("User or password, incorrect");
        }, TaskScheduler.FromCurrentSynchronizationContext());
}

答案 1 :(得分:1)

您需要在后台运行数据库连接。有很多方法可以做到这一点,但随着async/await的出现,这将是最简单的方法:

private async void btnLogin_Click (object sender, EventArgs e)
{
     loading.Visible = true;
     if (await Task.Run(() => ConnectDataBase()))
     {
         OpenForm2();
         This.Close();
     }
     else MessageBox.Show ("User or password, incorrect");
     loading.Visible = false;
}

请注意以下更改:

  • 我让方法async void向编译器发出信号,告诉我们要使用async/await
  • 我创建了一个运行数据库连接的任务:

    await Task.Run(() => ConnectDataBase())
    

    这将返回boolConnectDataBase()的结果将会返回Login 基本上和其他答案一样做同样的事情 减少手动杂乱和处理任务。

观察:通过这样的后台执行,用户可以再次单击private async void btnLogin_Click (object sender, EventArgs e) { btnLogin.Enabled = eUsername.Enabled = ePassword.Enabled = false; loading.Visible = true; ... rest of method loading.Visible = false; btnLogin.Enabled = eUsername.Enabled = ePassword.Enabled = true; } 按钮,同时第一次单击仍在执行(并尝试连接到数据库) )。您应该采取措施确保无法执行此操作,例如在执行此操作时禁用登录按钮(以及其他字段,例如用户名,密码等),例如:

ConnectDataBase

注意如果可能的话,最好将public static async Task<bool> ConnectDataBase() { var connection = new SqlConnection("connection string"); try { await connection.OpenAsync(); // store "connection" somewhere I assume? return true; } catch (SqlException) { connection.Dispose(); return false; } } 方法重写为异步,因为现在大多数.NET数据库连接服务都有方法来执行此操作。如果不了解这个方法的作用,我只能做一般性的评论。

以下是如何编写SQL Server连接尝试的示例:

if

通过此更改,您可以将原始方法中的 if (await ConnectDataBase()) - 语句更改为:

var path = require('path');
const webpack = require('webpack');
const helpers = require('./helpers');

var CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');

const ProvidePlugin = require('webpack/lib/ProvidePlugin');

const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ForkCheckerPlugin = require('awesome-typescript-loader').ForkCheckerPlugin;
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const METADATA = {
  title: 'My Website ',
  baseUrl: '/',
  isDevServer: helpers.isWebpackDevServer()
};
module.exports = {
  metadata: METADATA,
  entry: {
      'polyfills': './src/polyfills.ts',
      'vendor': './src/vendor.ts',
       'app': [
      './src/main'
    ]
  },
    amd: { jquery: true },
  resolve: {
    extensions: ['', '.ts', '.js', '.json', '.css', '.html'],

    root: helpers.root('src'),

      modules: ['node_modules']

  },

  module: {
      rules: [
          {
              enforce: 'pre',
              test: /\.ts$/,
              loader: 'tslint-loader'
          },
          {
              test: /\.ts$/,
              loaders: ['awesome-typescript-loader', 'angular2-template-loader', '@angularclass/hmr-loader'],
              exclude: [ /\.spec\.ts$/, /\.e2e\.ts$/, /node_modules/ ]
          },
          {
              test: /\.html$/,
              loader: 'html-loader'

          },
          {
              test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)(\?.*$|$)/,
              loaders: ['file?name=assets/images/[name].[hash].[ext]',
                  'image-webpack?bypassOnDebug&optimizationLevel=7&interlaced=false'
              ]
          },
          {
              test: /\.css$/,
              exclude: [helpers.root('src','app')],
              loaders: [ExtractTextPlugin.extract('style-loader', 'css-loader?sourceMap'), 'to-string' , 'css' ]
          },
          {
              test: /\.css$/,
              include: helpers.root('src', 'app'),
              loader: 'raw'
          },
          {
              test: require.resolve("jquery"),
              loader: "expose?$!expose?jQuery"
          }
      ],
        noParse: [
        /zone\.js\/dist\/.+/,
        /reflect-metadata/,
        /es(6|7)-.+/,
        /.zone-microtask/, 
        /.long-stack-trace-zone/
        ]

     },
  plugins: [
        new CopyWebpackPlugin([
            {
                from: 'src/assets/faq',
                to: 'assets/faq'
            },
            {
                from: 'src/assets/images',
                to: 'assets/images'
            },
            {
                from: 'src/assets/icons',
                to: 'assets/icons'
            },
             {
                from: 'src/assets/jsonProperty',
                to: 'assets/jsonProperty'
            },
            {
              from: './i18n',
              to: 'i18n'
            }]),

      new ProvidePlugin({
          $: "jquery",
          jquery: "jquery",
          jQuery:"jquery",
          "windows.jQuery": "jquery"

      }),
    new CommonsChunkPlugin({ name: ['app', 'vendor', 'polyfills']}),

    new HtmlWebpackPlugin({
      template: './src/index.html',
      favicon:"./src/favicon.ico",
      minify:false,
      chunksSortMode: 'dependency'
    })
   ],
  node: {
    global: 'window',
    crypto: 'empty',
    process: true,
    module: false,
    clearImmediate: false,
    setImmediate: false
  }

};